我在编组方面遇到了一些问题,而我自己也无法解决这个问题。我已经搜索了这个主题,但还没有运气,所以基本上我试图从我的托管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。
对此有任何帮助将不胜感激。
答案 0 :(得分:8)
将函数声明为:
[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 ++中的长度为32位,因此您应该在C#代码中将所有此类实例定义为int。