6

我在编组方面遇到了一些问题,我自己无法弄清楚。我已经搜索了这个主题,但还没有任何运气,所以基本上我试图从我的托管 C# 应用程序中调用一个非托管 C 函数。C 函数的签名如下所示:

long MyFunction(WCHAR* upn, long upnSize, WCHAR* guid, long* guidSize);

我没有访问 .dll 文件,我只知道该函数正在被公开使用并且我知道该函数应该做什么,但我不知道里面发生了什么,所以该函数接收一个 WCHAR* upn 持有一个 UserPricipalName 和一个 long 与提供的 UPN 的长度。还传递了一个 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。

对此的任何帮助将不胜感激。

4

1 回答 1

10

将函数声明为:

    [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。

于 2012-08-09T08:31:36.160 回答