【发布时间】:2019-12-08 01:21:06
【问题描述】:
我在C中有以下方法
void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
int (*cb) (SSL *ssl,
const unsigned char *cookie,
unsigned int cookie_len))
{
ctx->app_verify_cookie_cb = cb;
}
我希望在 C# 中调用它。我正在尝试这样:
[DllImport(SSLDLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern void SSL_CTX_set_cookie_verify_cb(IntPtr ctx, VerifyCookieDelegate callback);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int VerifyCookieDelegate(IntPtr ssl, [MarshalAs(UnmanagedType.LPStr)] string cookie, int cookie_len);
不幸的是,当回调运行时,返回后,进程死于SIGSEGV(segfault)
public int VerifyCookieThunk(IntPtr sslPtr, IntPtr cookie, int cookieLength)
{
if (!TryGetInstance(sslPtr, out Ssl ssl))
return Native.FAIL;
var c = new byte[cookieLength];
Marshal.Copy(cookie, c, 0, cookieLength);
if (_verifyCookieCallback(ssl, c))
return 1;
return 0;
}
我觉得奇怪的是,当回调返回时会发生段错误。所以我想也许我还需要保留对返回值的引用。于是我做了一个类变量(类不是GCd):
private int verifyCookieResult;
现在在回调中我设置并返回verifyCookieResult。仍然是 SEGFAULT。
您可能认为本机代码中存在错误,但实际上没有。这个相同的功能在不同的上下文中工作。
我写代码设置回调函数的方式有问题吗?
【问题讨论】:
-
有没有可能你已经在 32 位模式下编译了你的 C 代码,而你在 64 位模式下运行 C#?您确定两者都以相同的模式编译/运行吗?
-
“它在不同的上下文中工作”与“无错误”不同。作为一个常见问题:未管理的代码是针对 x32 或 x64(有时是 x16)编译的。同时,MSIL 与位无关,因此相同的代码可以以 x32 或 x64 运行——如果我们获得运行时,甚至可以以 x16 或 x128 运行。这是由运行时根据项目的目标设置决定的。这里的不匹配导致了无数此类问题。
-
cookie的类型不匹配 - 你在一个地方有string,在另一个地方有IntPtr? -
还要确保您保留对
VerifyCookieDelegate实例的引用,否则VerifyCookieDelegate可能会在C 端调用它之前在.NET 端进行GC。这不会导致您当前的问题,但这是一个常见的问题。
标签: c# pinvoke marshalling unmanaged