5

私は C++ (MSVC) ライターであり、VB の初心者であり、この作業を行ったことのない専門の VB.net ライターを支援しようとしています。

C/C++ と VB の両方のアプリケーションを開発して、C++ で記述された DLL と C の外部 API 関数を使用したいと考えています。C++ プログラムは正常に動作しています。私たちが問題を抱えているのはVBです。

DLL は次のextern C機能を提供します。

RegisterCallback( void* cbFuncPtr, void* dataPtr );

注 1: デザインの変更とその理由については、以下のメモを参照してください。

注2:以下の回答として追加の更新が追加されました。

コールバック関数には、次の C 型定義があります。

typedef   (void)(* CALL_NACK)(void*);

これcbFuncPtrは、CALL_BACK として呼び出される VB 関数への関数ポインタであると予想されます。は、次のdataPtrC 定義を持つデータ構造へのポインターです。

typedef struct 
{
   int      retCode;
   void*    a_C_ptr;
   char     message[500];
}  cbResponse_t;

どこにa_C_ptr is an internal pointer in the DLL that the VB can cast to長い`。コールバックが作成された DLL 内の場所を一意に識別し、VB 関数が同じ場所または異なる場所からの呼び出しを認識できるようにします。

RegisterCallback()VB から関数にアクセスして実行することができます。ロギングは、そこに到達し、データが渡されたことを示しています。問題のように見えるのは実際のデータです。

約 100 万件のフォーラム エントリを読んで、VB はポインタが何であるかを認識せず、VB の構造は単なる整理されたメモリ以上のものであることを学びました。VB 構造体の「アドレス」が、C がアドレスと考えるものではないことは確かです。「マーシャリング」と「管理されたデータ」への言及を繰り返し見てきましたが、それが何を伝えているのかを知るには十分な理解がありません。

コールバック関数の実行アドレスを DLL に与えるために VB をどのようにコーディングすればよいでしょうか? また、C++ の場合と同様に、DLL が埋めることができる VB 構造をどのようにコーディングすればよいでしょうか?

呼び出し元のアプリが "C" または "VB" と言うことができ、DLL が構造ポインターを別の方法で処理できるようにする DLL 関数が必要でしょうか? もしそうなら、どのように C をコード化して VB 構造を埋めますか?

4

2 に答える 2

1

これは、元の投稿を編集するには、大きすぎて深すぎます...

@DaveNewman が投稿したリンクから、この宝石を抽出しました。


コンパクトなフレームワークについて少し説明しますが、大人のフレームワークでも同じです。

.NET Compact Framework は、単純型を含む構造体とクラスの自動マーシャリングをサポートしています。すべてのフィールドは、構造体またはクラス定義に表示されるのと同じ順序でメモリに順番に配置されます。クラスと構造体はどちらも、C/C++ 構造体へのポインターとしてネイティブ コードに表示されます。

マネージド ヒープ内のオブジェクトは、ガベージ コレクターによっていつでもメモリ内を移動できるため、それらの物理アドレスは予告なく変更される場合があります。P/Invoke は、各メソッド呼び出しの間、参照によって渡されたマネージド オブジェクトを自動的に固定します。これは、アンマネージ コードに渡されたポインターがその 1 回の呼び出しに対して有効であることを意味します。後続の呼び出しでオブジェクトが別のメモリ アドレスに移動されないという保証はないことに注意してください。

http://msdn.microsoft.com/en-us/library/aa446538.aspx#netcfmarshallingtypes_topic6


これはRegisterCallback( fcnPtr, dataPtr)関数の大きなハードルです。RegisterCallback()登録時に渡されたポインターは、現在のステートメントではなく、いつでも変更される可能性があります。投稿者はこのように要約しました

通話中は構造が自動的に固定されるため、何もする必要はありません。

もちろん、通話の外に固定されていないことを意味します。

このため、VB の領域ではなく、いわば DLL の C/C++ の世界に応答構造を組み込むように設計を変更することにしました。そうすればそのままです。実際のコールバック関数のシグネチャは変更されないため、VB プログラムは DLL が応答を配置した場所を知ることができます。これにより、DLL 内のレスポンダーは、個別のニーズに個別の応答構造を割り当てることもできます。

于 2013-04-11T11:41:17.053 に答える