使用out修饰符传递非托管代码的指针

时间:2016-05-13 14:22:10

标签: c# interop pinvoke dllimport

我有一个(C / C ++)DLL,我通过DLLImport调用C#项目。 这个DLL有这个方法:

int __stdcall Connect(OUT int *p_sessionID, IN BYTE mode, IN BYTE comport, IN char *servername, IN DWORD serverport);

我尝试了几种方式来翻译"它到C#,但我发现更接近的是:

[DllImport("UnmanagedDLL.dll", EntryPoint = "Connect", CallingConvention = CallingConvention.StdCall)]
private static extern unsafe int CS1_Connect(out IntPtr p_sessionID, byte mode, byte comport, string servername, int serverport);

我试图像这样调用:

IntPtr connection;
var i = Connect(out connection, 1, 0, "192.0.0.1", 1982);

但我总是收到以下错误:

附加信息:调用PInvoke函数' DllImportTest!DllImportTest.Program :: Connect'堆栈不平衡。这很可能是因为托管PInvoke签名与非托管目标签名不匹配。检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。

我知道我可以访问DLL,因为我有另一种方法可以正常工作。

我做错了什么?

感谢。

1 个答案:

答案 0 :(得分:0)

您的第一个参数翻译错误。

OUT int *p_sessionID

这里OUT是一个宏,表示读者的语义。宏将它扩展为空。所以在预处理之后你就有了:

int *p_sessionID

翻译为

out int sessionID

在您的C#中。

您不需要将该函数声明为不安全,请删除它。最后一个参数是无符号的。您可能希望切换到uint

因此,正确的翻译是:

[DllImport("UnmanagedDLL.dll", EntryPoint = "Connect", 
    CallingConvention = CallingConvention.StdCall)]
private static extern int CS1_Connect(
    out int sessionID, 
    byte mode, 
    byte comport, 
    string servername, 
    uint serverport
);

如果您仍然收到堆栈不平衡消息,那么您将知道非托管函数没有您在问题中引用的签名。