6

マーシャリングに少し問題があり、自分で理解することはできません。このトピックを検索しましたが、まだ運がなかったので、基本的に、マネージドC#アプリケーションからアンマネージドC関数を呼び出そうとしています。C関数のシグネチャは次のようになります。

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

.dllファイルにアクセスしていません。関数が使用できるように公開されていることと、関数が何を実行するかはわかっていますが、内部で何が起こっているのかわからないため、関数はWCHAR*を受け取ります。 UserPricipalNameを保持する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を読み取ることができませんでした。

これに関する助けをいただければ幸いです。

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 に答える