c# - 如何使用 WCHAR* out 参数从 C# 调用 C 函数?

标签 c# c interop marshalling

我在编码方面遇到了一些问题,我自己无法解决。我已经搜索过这个主题,但还没有任何运气,所以基本上我试图从我的托管 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/

相关文章:

C#字节操作优化: how to get dword from byte[] array

c - 无法正确访问结构体内容

c++ - 这两行代码有什么区别

c++ - CoCreateInstance 使用 CLSCTX_LOCAL_SERVER 是否足以确保所有应用程序共享 COM 对象实例?

c# - Microsoft.Office.Interop.Outlook 错误 - 文件 filename.ics 不是有效的 Internet 日历文件

.net - 如何在 C# 中声明联合?

c# - 这个 lambda 表达式的返回类型应该是什么?

c# - NHibernate - 通过不同的键多个 JOIN 到同一个表

c# - .NET 将对象转换为...对象的目标是什么?

c - QDBus 与我的服务器一起工作作为客户端而不是 GDbus