1

C++ ライブラリの関数にアクセスするために、C# でクラスを作成しようとしています。C++ dll の関数:
bool WriteReply(const unsigned char *reply, const unsigned long reply_length).

C++ での使用方法のサンプル:-

unsigned short msg_id = 0x0000;                      
byte msg_body[] = {(byte)(GetTickCount()/0x100)};    // a random value for loopback data

    // combine the message id and message body into an big msg
    unsigned long msg_length = sizeof(msg_id)+sizeof(msg_body);
    byte* big_msg = new byte[msg_length];
    big_msg[0] = LOBYTE(msg_id);
    big_msg[1] = HIBYTE(msg_id);
    memcpy((void*)&big_msg[2], (void*)msg_body, sizeof(msg_body));

    // send the big message
    if (!big_dev.WriteReply(big_msg, msg_length))
    {
        //do something here
    }

関数を c# から dll ( AccessViolationException) に渡すことができないようです。これは私が試したコマンドです:-

byte[] bytearray = new byte[3] { 0x01, 0x02, 0x03 };
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytearray.Length);
Marshal.Copy(bytearray, 0, unmanagedPointer, bytearray.Length);

bool writestatus = (bool)NativeMethods.WriteReply(unmanagedPointer, (uint)bytearray.Length);

そしてインポート側: -

[DllImport("dllname.dll", EntryPoint = "WriteReply")]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool WriteReply(IntPtr msg, uint reply_length);

どこが間違っているのか教えてください?ありがとう!

4

2 に答える 2

0

C ++メソッドが文字列を使用し、それを変更しないと仮定します...

これを試して

__declspec(dllexport) bool __cdecl WriteReply(const unsigned char *reply, const unsigned long reply_length);


[DllImport("libfile.dll", EntryPoint = "WriteReply")]
private static extern bool WriteReplyExternal(
    [MarshalAs(UnmanagedType.LPStr)] [Out] string replyString,
    [Out] UInt32 replyLength);

または、さらに良い方法です(C文字列はnullで終了し、バッファーは読み取り専用であるため、バッファーオーバーフローについて心配する必要はないため、長さパラメーターは冗長です):

__declspec(dllexport) bool __cdecl WriteReply(const unsigned char *reply);


[DllImport("libfile.dll", EntryPoint = "WriteReply")]
private static extern bool WriteReplyExternal(
    [MarshalAs(UnmanagedType.LPStr)] [Out] string replyString);

これらは、メソッドがクラス内にない場合に機能します。そうでない場合は、エントリポイントとしてC++のマングル名を使用する必要があります。

文字列に1...127 ASCII範囲外の文字(英語以外の文字など)が含まれている場合は、C ++ではcharの代わりにwchar_tを使用し、マーシャリングではLPStrの​​代わりにLPWStrを使用する必要があります。

編集:

プライベートメソッドを、.NETにより適したシグネチャを持つ別のメソッドでラップする必要があります。

public void WriteReply(string message)
{
    var result = WriteReplyExternal(message, message.Length);
    if (result == false)
        throw new ApplicationException("WriteReplay failed ...");
}
于 2012-04-29T11:14:17.103 に答える
0

最近追加されたコードは、実際の問題に関する手がかりを提供すると思います。

if (!big_dev.WriteReply(big_msg, msg_length))

WriteReplyはメンバー関数であるため、これは機能しません。C ++メンバー関数ではなく、Cスタイルの関数を呼び出す必要があります。後者にはインスタンスが必要です(big_devコードサンプル内)。

于 2012-04-30T11:47:45.077 に答える