我在编码方面遇到了一些问题,我自己无法解决。我已经搜索过这个主题,但还没有任何运气,所以基本上我试图从我的托管 C# 应用程序调用一个非托管 C 函数。 C 函数的签名如下所示:
long MyFunction(WCHAR* upn, long upnSize, WCHAR* guid, long* guidSize);
我无法访问 .dll 文件,我只知道该函数正在公开使用并且我知道该函数应该做什么,但我不知道里面发生了什么,所以该函数接收一个包含 UserPricipalName 的 WCHAR* upn 和一个带有提供的 UPN 长度的 long。还传递了一个 WCHAR 指针,其中函数写回与传递的 UPN 关联的相应 GUID。 guidSize 指针提供指针的大小,如果它太小,则写入的 GUID 未完全写入。如果一切顺利,该函数应该返回 0(它从未发生过,当从 c# 调用时)
现在我调用这个函数的努力看起来像这样:
[DllImport(@"MyDll.dll", EntryPoint = "MyFunction", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern long MyFunction(IntPtr upnPtr, long upnSize, [Out, MarshalAsAttribute(UnmanagedType.LPWStr) ] StringBuilder guidPtr, IntPtr guidSizePtr);
//my attempt to call the Dll's exposed function
string upn = foo@bar.com;
long upnSize = upn.Length;
IntPtr upnPtr = Marshal.StringToHGlobalUni(upn);
IntPtr guidSizePtr = Marshal.AllocHGlobal(sizeof(long));
Marshal.WriteInt32(GuidSizePtr, 128);
var guidSB = new StringBuilder(128);
result = MyFunction(upnPtr, upnSize, guidSB, guidSizePtr);
因此我收到了 AccessViolationException。我试过很多变体来调用该函数,但我从来没有设法收到 0 作为返回值,而且我从来没有能够像我应该做的那样读出 GUID。
如有任何帮助,我们将不胜感激。
最佳答案
将函数声明为:
[DllImport(@"MyDll.dll", EntryPoint = "MyFunction", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern int MyFunction([MarshalAsAttribute(UnmanagedType.LPWStr)] string upnPtr, int upnSize, [MarshalAsAttribute(UnmanagedType.LPWStr)] StringBuilder guidPtr, ref int guidSizePtr);
调用如下:
string upn = "foo@bar.com";
var guidSB = new StringBuilder(128);
int guidSizePtr =guidSB.Capacity;
MyFunction(upn, upn.Length, guidSB, ref guidSizePtr);
请注意,C++ 中的 long 是 32 位的,因此您应该在 C# 代码中将所有此类实例定义为 int。
关于c# - 如何使用 WCHAR* out 参数从 C# 调用 C 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11879108/