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

Passing pointers from unmanaged code with out modifier

我有一个 (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);

我尝试了几种方法 "translate" 它到 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,因为我有另一种工作正常的方法。

我做错了什么?

谢谢。

您的第一个参数翻译不正确。

OUT int *p_sessionID

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

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
);

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