简体   繁体   English

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

[英]how to call a C function from C# with a WCHAR* out parameter?

I'm having a bit of problem with marshaling and I just can't figure it out by myself. 我在编组方面遇到了一些问题,而我自己也无法解决这个问题。 I've searched for this topic, but hadn't have any luck yet, so basically I'm trying to call an unmanaged C function from my managed C# application. 我已经搜索了这个主题,但还没有运气,所以基本上我试图从我的托管C#应用程序调用非托管C函数。 The signature of the C function looks like this: C函数的签名如下所示:

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

I don't access to the .dll file, I just know that the function is being exposed for usage and I know what the function is supposed to do, but I don't know what happening inside, so the function receives a WCHAR* upn holding a UserPricipalName and a long with the length of the supplied UPN. 我没有访问.dll文件,我只知道该函数正在暴露使用,我知道该函数应该做什么,但我不知道里面发生了什么,所以函数收到一个WCHAR * upn持有UserPricipalName和长度与提供的UPN的长度。 Also a WCHAR pointer is passed along, where the function writes back a corresponding GUID which is associated with the passed UPN. 还传递WCHAR指针,其中该函数写回与传递的UPN相关联的相应GUID。 The guidSize pointer supplies the size of the pointer, if it's too small the written GUID is not fully written. guidSize指针提供指针的大小,如果它太小,则写入的GUID未完全写入。 If everything goes fine the function should return 0 (it never happened yet, when called from c#) 如果一切顺利,函数应该返回0(当从c#调用时,它从未发生过)

Now my efforts to invoke and call this function look like this: 现在,我调用和调用此函数的努力如下所示:

[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);

as a result I receive an AccessViolationException. 结果我收到一个AccessViolationException。 I've played around with many variations to call the function, but I never managed to receive a 0 as return value and I was never able to read out the GUID as I'm supposed to do. 我玩了很多变种来调用函数,但我从来没有设法收到0作为返回值,我从来没有能够读出GUID,因为我应该这样做。

Any help with this would be appreciated. 任何帮助都将不胜感激。

Declare the function as: 将函数声明为:

    [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);

Call it as follows: 称其如下:

        string upn = "foo@bar.com";
        var guidSB = new StringBuilder(128);
        int guidSizePtr =guidSB.Capacity;
        MyFunction(upn, upn.Length, guidSB, ref guidSizePtr);

Note that long in C++ is 32-bit, so you should define all such instances as int in your C# code. 请注意,C ++中的长度为32位,因此您应该在C#代码中将所有此类实例定义为int。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM