2011-04-03 194 views
0

如何从C#中调用以下方法,该方法位于C++ dll中?我如何在C#中重新创建以下结构?如何从C#代码调用非托管dll中的函数?


原始

方法:

LONG MyMethod (P_HOLO_INFO pInfo, LPVOID pBuffer, LPUSHORT pTracksWritten); 

结构:该方法使用以下结构:

typedef struct _HOLO_INFO 
{ 
    LONG  lHoloType; 
    LONG  lStatus; 
    HANDLE lThreadHandle; 
    LONG  lErrorCode; 
    LONG  lDriveIndex; 
    LONG  lHeight; 
    SHORT iFormat; 
    INT  iStartingTrack; 
    LONG  lWrite; 
    LONG  lSkip; 
    BOOL  bSkipZero; 
    BOOL  bInvert; 
    LONG  lMaxConsecutiveErrors; 
    LONG  lMaxTotalErrors; 
    LONG  lMostConsecutiveErrors; 
    LONG  lTotalErrors; 
    LPBYTE pBuffer; 
    LPUSHORT pTracksWritten; 
    LONG  bUpsideDown; 
} HOLO_INFO, *P_HOLO_INFO; 

我曾在C#这样

方法:

[DllImport("My.dll", EntryPoint = "[email protected]")] 
public unsafe static extern long MyMethod(ref HOLO_INFO pInfo, Byte[] pBuffer,ref ushort pTracksWritten); 

结构:

该方法使用以下结构:

unsafe public struct HOLO_INFO 
{ 
    public long lHoloType; 
    public long lStatus; 
    public long lThreadHandle; 
    public ulong lErrorCode; 
    public long lDriveIndex; 
    public long lHeight; 
    public short iFormat; 
    public int iStartingTrack; 
    public long lWrite; 
    public long lSkip; 
    public bool bSkipZero; 
    public bool bInvert; 
    public long lMaxConsecutiveErrors; 
    public long lMaxTotalErrors; 
    public long lMostConsecutiveErrors; 
    public long lTotalErrors; 
    public Byte* pBuffer; 
    public long* pTracksWritten; 
    public long bUpsideDown; 
}; 

我进行的呼叫以这样的方法:

do 
    { 
    result = MyMethod(ref pInfo,ptrBuf,pTracksWritten); 
    } while (result ==1); 

因为,它返回1,如果是有源 0,如果它成功完成 3,如果因为错误而停止。如果方法处于运行状态(Active-1),则为 。它修改pInfopTracksWritten更新状态信息。

+1

我不得不做类似的事情。我所做的就是将DLL包装在CLRC++类中,并在一侧获得C++结构,并在另一侧返回CLR兼容结构,但是这是一段时间后,现在可能有更好的方法。 – 2011-04-03 14:55:22

+0

你在这里显然是正确的。如果我是你,我会用C++编写一个特殊的测试函数来消除细节。让它将输入写入文件。然后您可以检查您从C#发送的内容是否正确。对于任何其他方向的数据传递,请让测试C#程序也登录到文件。 – 2011-04-03 16:27:31

回答

0

Using a Very C# DLL in C++

你可以做一个“简单”的把戏[这个答案(答案Using a Very C# DLL in C++),或者你可以看看茂盛的嵌入按照my answer

+0

我需要在C#中使用C++ dll。 – aWebdesigner09 2011-04-03 15:21:39

+0

我一定一直在睡觉。有一个VS插件将C proto +声明翻译成P/Invoke内容...如果我有时间,我会再次找到它 – sehe 2011-04-03 15:23:44

+0

@ aWebdesigner09:标题误导,听起来像是你想要的相反。我编辑它。 – ildjarn 2011-04-03 15:23:51

3

很多问题:

  • LONG应该在C#中声明为int
  • HANDLE是IntPtr。
  • pTracksWritten丢失。您可能需要制作它,而pBuffer,一个IntPtr并使用Marshal.AllocHGlobal为它们分配内存。
  • 您需要[DllImport]声明中的CallingConvention才能使用Cdecl。

如果您无法调试非托管代码,那么获得这个工作的可能性并不是很大。一个基本的理智测试是确保元帅。SizeOf()在非托管代码中返回与sizeof()相同的长度。接下来验证在调试本机代码时传递的参数看起来不错。接下来,检查本机代码中的指针使用情况,并确认它们未被复制。

+0

如果可能,请提供完整的答案。我花了很多时间寻找和尝试不同的方式。非常感谢您的快速反应。 – aWebdesigner09 2011-04-03 15:18:12

+2

我只是给你适当的口径子弹。把枪指向你的脚是你得到的报酬。在C++/CLI中执行此操作将是明智的。 – 2011-04-03 15:19:16

+1

@ 12建议stdcall – 2011-04-03 16:09:36

0

这给一个镜头:

[DllImport("My.dll", EntryPoint = "[email protected]")] 
int MyMethod (HOLO_INFO pInfo, IntPtr pBuffer, IntPtr pTracksWritten); 

public class HOLO_INFO 
{ 
    public int lHoloType; 
    public int lStatus; 
    public IntPtr lThreadHandle; 
    public int lErrorCode; 
    public int lDriveIndex; 
    public int lHeight; 
    public short iFormat; 
    public int iStartingTrack; 
    public int lWrite; 
    public int lSkip; 
    public bool bSkipZero; 
    public bool bInvert; 
    public int lMaxConsecutiveErrors; 
    public int lMaxTotalErrors; 
    public int lMostConsecutiveErrors; 
    public int lTotalErrors; 
    public IntPtr pBuffer; 
    public IntPtr pTracksWritten; 
    public int bUpsideDown; 
} 

取决于他们是如何分配的,你可能需要使用Marshal.Copy访问HOLO_INFO.pBufferMarshal.PtrToStructure访问HOLO_INFO.pTracksWritten(或Marshal.Copy,如果它是一个数组与指针一个奇异的值)。

+0

调用约定将stdcall – 2011-04-03 16:22:35

+0

你肯定意味着:'int MyMethod(ref HOLO_INFO Info,IntPtr pBuffer,out UInt16 TracksWritten);' – 2011-04-03 16:25:25

+0

@David Heffernan:没有。 'DllImport'的默认调用约定是stdcall,但VC++的默认值是cdecl(请参阅http://msdn.microsoft.com/en-us/library/46t77ak2.aspx)。关于'ref','HOLO_INFO'是一个'class',所以它已经通过引用传递;使用'ref'将会类似于C++中的'HOLO_INFO **'或'P_HOLO_INFO *'。关于'out ushort',在我看来'HOLO_INFO.pTracksWritten'可能最终会保存该指针值,如果没有使用明确的堆分配,在函数返回后该指针值将无效。 – ildjarn 2011-04-03 16:29:41