4

C#で使用したいC++クラスがあります。そうするために、私は他のC ++ dllを作成して、このクラス(他のライブラリの一部)を呼び出し可能な関数( "extern C and __declspec(dllexport)"を使用)でラップしようとしています。私の考えは、オブジェクトへのポインターを保持し、それをラッパーdllの関数に送信して、そこからそのオブジェクトのメソッドを呼び出すことです。これは問題ないように見えますが、オブジェクトにデコンストラクターがあると問題が発生します。

これが私のC++ラッパーコードです:(デバイスは私のC++クラス/オブジェクトです)

__declspec(dllexport) Status Device_open(Device* di, const char* uri)
{
     Device dl;
     Status status = dl.open(uri);
     di = &dl;
     return status;
}
__declspec(dllexport) void Device_Close(Device* di)
{
     di->close();
}

これが私のC#ラッパーコードです:

    [DllImport("Wrapper.dll")]
    static extern Status Device_open(ref IntPtr objectHandler, IntPtr uri);
    public static Device Open(string uri)
    {
        IntPtr handle = IntPtr.Zero;
        Device_open(ref handle, Marshal.StringToHGlobalAnsi(uri));
        return new Device(handle);
    }
    [DllImport("Wrapper.dll")]
    static extern void Device_Close(IntPtr objectHandler);
    public void Close()
    {
        Device_Close(this.Handle);
    }

C#アプリケーションでのテストコードは次のとおりです。

    Device d = Device.Open(di.URI);
    d.Close();

すべてが良いです。ここで問題となるのは、新しいデバイスを開くように要求すると、メインC ++オブジェクトのDeconstructorが実行されるため、閉じる要求は常に例外を返すことです(すでに閉じられているか破棄されているため)。

これを防ぐために何ができますか?!

4

1 に答える 1

5

関数のDevice最後でスコープ外であるため、 は破棄されていDevice_open()ます。Device解決するには、を使用してインスタンスを動的に割り当てます。newこれにより、 の有効期間を制御dlできます。次にdelete dl;Device_Close()関数で。

C++ 関数はDevice*、関数に対してローカルな a にアドレスを割り当てていることに注意してください。呼び出し元には表示されません。これを修正するには、C++ 側でポインターを参照渡しします。

__declspec(dllexport) Status Device_open(Device*& di, const char* uri)

または、 を渡すことができますDevice**

__declspec(dllexport) Status Device_open(Device** di, const char* uri)

ただし、これが c# 側にどのように影響するかはわかりません。

メモリ リークを防ぐには、呼び出しが失敗した場合に のnewインスタンスDevicedeletedであることを確認します。dl.open(url)

__declspec(dllexport) Status Device_open(Device*& di, const char* uri)
{
    Status status;
    try
    {
        Device* dl = new Device();
        status = dl->open(uri);
        if (status != OK)
        {
            delete dl;
        }
        else
        {
            di = dl;
        }
    }
    catch (std::bad_alloc const&)
    {
        status = BAD_ALLOC; // Or equivalent failure reason.
    }
    return status;
}

__declspec(dllexport) void Device_Close(Device* di)
{
     // di->close(); Uncomment if destructor does not close().
     delete di;
}
于 2013-02-11T17:15:28.590 に答える