1

void** を取る関数を含む古い C ライブラリがあります。

oldFunction(void** pStuff);

マネージ C++ からこの関数を呼び出そうとしています (m_pStuff は void* 型の親 ref クラスのメンバーです):

oldFunction( static_cast<sqlite3**>(  &m_pStuff ) );

これにより、Visual Studio から次のエラーが表示されます。

エラー C2440: 'static_cast': 'cli::interior_ptr' から 'void **' に変換できません

私は、コンパイラが void* メンバー ポインターを背後で cli::interior_ptr に変換していると推測しています。

これを行う方法に関するアドバイスはありますか?

4

2 に答える 2

1

編集:修正された答え、以下を参照してください。

実際には、oldFunction が pStuff で何をしようとしているのかを知る必要があります。pStuff が管理されていないデータへのポインタである場合は、m_pStuff の定義を次のようにラップしてみてください。

#pragma unmanaged

void* m_pStuff

#pragma managed

これにより、ポインターがアンマネージになり、アンマネージ関数に渡すことができます。もちろん、管理対象オブジェクトをこのポインタに直接割り当てることはできません。

基本的にアンマネージド ポインターとマネージド ポインターは同じではなく、基になるデータをコピーする何らかのグルー コードがないと変換できません。基本的にマネージド ポインターはマネージド ヒープを指します。これはガベージ コレクションであるため、ポインターが指す実際のメモリ アドレスは時間の経過とともに変化する可能性があります。アンマネージ ポインターは、明示的に変更しない限り、メモリ アドレスを変更しません。

クラス定義内で unmanaged / managed を定義することはできません。しかし、このテスト コードは問題なく動作するようです。

// TestSol.cpp : main project file.

#include "stdafx.h"

using namespace System;

#pragma unmanaged

void oldFunction(void** pStuff)
{
    return;
}

#pragma managed

ref class Test
{
public:
    void* m_test;

};

int main(array<System::String ^> ^args)
{
    Console::WriteLine(L"Hello World");

    Test^ test = gcnew Test();
    void* pStuff = test->m_test;
    oldFunction(&pStuff);
    test->m_test = pStuff;

    return 0;
}

ここでは、最初にマネージド オブジェクトからポインターをコピーしてから、それを oldFunction に渡します。次に、結果 (おそらく oldFunction によって更新されたもの) を管理対象オブジェクトにコピーします。マネージド オブジェクトはマネージド ヒープ上にあるため、ガベージ コレクターの実行時にポインターが移動する可能性があるため、コンパイラーはそのオブジェクトに含まれるポインターへの参照を渡すことを許可しません。

于 2008-08-26T03:06:46.177 に答える
0

アドバイスをありがとう、ポインタはCスタイルの抽象構造へのものであり、その構造をマネージコードに公開したままにしておくと、定義された構造がないためにさらに苦痛を引き起こすと思います。したがって、C ライブラリを C++ でラップしてから、C++ ラッパーをマネージ C++ でラップすると、これらの C 構造がマネージ コードに公開されるのを防ぐことができます。

于 2008-08-26T17:37:02.963 に答える