2

私はC++でDLLを作成してきましたが、VB6アプリケーションからこのDLLを呼び出す必要があります。

このDLLのコードサンプルは次のとおりです。

#include <vector>
#include <string>

using namespace std;    

void __stdcall DLLFunction (vector<Object>*)
{
 // performs a few operations on the Objects contained in the vector.
}

struct Object
{
    long CoordX;
    long CoordY;
    long Width;
    long Height;
    LPSTR Id;
};

また、VB6で「オブジェクト構造体」を定義しました

Private Type Object
    CoordX As Integer 
    CoordY As Integer 
    Width As Integer
    Height As Integer
    Id As String 
End Type

問題は、DLLの関数を呼び出すためにvb6タイプがstd::vectorを表すことができるかどうかわからないことです。

注:
-オブジェクトを追加できるようにするために、DLLのベクトルを使用します。
-できるだけ少ないメモリを使用するために、ポインタを使用します。
-私の英語は申し訳ありませんが、それは私の母国語ではありません。
-読んで助けてくれてありがとう。

編集:
-タイピングの問題を修正しました(IDは間違いなくNullCharで終了するため、LPSTRでうまくいくはずです)。-私はあなたの答えを読みました、そして私はあなたの両方に感謝したいと思います、あなたの答えは互いに近く、大きな問題が残っています。私のDLLは間違いなくコンテナに要素を追加する必要があります。したがって、私はどうやってそのトリックを行うことができるのだろうかと思っています。たぶん、関数にreturn型を追加して、関数が(コンテナーに直接入れるのではなく)作成したアイテムを返すことができるようにして、vb6アプリケーションがこれらのアイテムを取得して処理できるようにすることもできますが、これを行う方法がわかりません

ビスを編集:

@Rook:新しい構造体を使用することでこれを達成できると思います。
struct ObjectArrayPointer
{
Object * Pointer;
size_tカウンター;
}

そして、このように私の関数を呼び出します:

void __stdcall DLLFunction (ObjectArrayPointer*);

その後、オブジェクトを追加し、VB6アプリケーションのサイズパラメーターを編集して、これらの新しいオブジェクトを見つけることができます。それはあなたが意味したことでしたか?

4

3 に答える 3

5

とにかくDLLからテンプレートコンテナをエクスポートしようとしてはいけません。新しいコンパイラやライブラリに直面すると、壊れてしまう可能性があります(たとえば、C ++ 03で構築されたライブラリは、C ++ 11を使用して構築されたコードではうまく機能しません)。

最も簡単なことは、バッファへのポインタと長さパラメータを受け入れることです。

void __stdcall DLLFunction (Object* buffer, size_t nObjects);

実行中にコンテナのサイズが変更されない場合。このインターフェイスは、ほぼすべての単純なものであり、Cの呼び出し規約を理解しているすべての言語(たとえば、ほぼすべての言語)から簡単にアクセスできます。

std::vectorあなたはすでにそれをに特化しているので、あなたはすでにほとんどの使用を捨てましたObject; ずっと進んで、内部的に使用するがテンプレート化されていないインターフェースを提示する独自のObjectCollectionクラスを作成することを検討できます。std::vector簡単な例を次に示します。

// In your public API header file:
typedef struct object_collection_t *object_collection;

object_collection CreateObjectCollection();
void DestroyObjectCollect(object_collection collection);
void AddObjectToCollection(object_collection collection, Object* object);
// etc

テンプレートタイプは、ヘッダーのどの形式でも公開されません。これはいい。

// And the corresponding code file:

struct object_collection_t
{
    std::vector<Object*> objects;
};

object_collection CreateObjectCollection() { return new object_collection_t; }
void DestroyObjectCollect(object_collection collection) { delete collection; }
void AddObjectToCollection(object_collection collection, Object* object)
{
    collection->objects.push_back(object);
}
// etc

テンプレートコードはすべて隠されており、外部コードで渡すことができるが、独自のコードでのみクエリおよび変更できる不透明なポインタ型を提供する、かなりクリーンでシンプルなインターフェイスが残ります。

編集:ちなみに、私はObject*上記のコード全体で使用しました。Object昔ながらの方法を使用して、メモリ管理とクライアントコードによるポインタ操作に関連するすべての問題を回避する方が、安全でわかりにくい場合があります。が十分に小さくて単純な場合Objectは、値を渡す方が適切なアプローチになる可能性があります。

(注:コンパイル可能性または機能性についてはチェックされていません。E&OE。警告実装者!)

于 2012-06-27T08:52:37.880 に答える
1

これはC++クラス/テンプレートであるため、これを行うことはできません。内部的にはアレイですが、VB6から作成できる方法ではありません。

最善の策は、countパラメーターを持つ配列へのポインターを受け入れるように関数を変更することです。

また、型がどのように構成されているかについても非常に注意する必要があります。

  1. C++はVB6のsですintLong
  2. また、Id文字列には互換性がありません。VB6にはユニコードBStringへのポインタがあり(固定長にしない限り)、C++にはANSI文字の配列であるstd::stringがあります。オブジェクトの配列(ポインタではなく)を渡す場合、VB6はこれをマーシャリングできます(
于 2012-06-27T08:39:51.663 に答える
1

VB6ABIはCOM自動化ABIです。

したがって、VB6 ABI互換のarryが必要な場合は、おそらくSAFEARRAYを使用する必要があります。コンパイラCOMサポートクラスも使用することをお勧めします。

http://msdn.microsoft.com/en-US/library/5yb2sfxk(v=vs.80).aspx

この質問は、ATLのCComSafeArrayクラスを使用して、あなたが望むことを正確に実行しているように見えます。

これらも確認することをお勧めします。

SAFEARRAYの代替

SAFEARRAYの代わりに、COMコレクションオブジェクトを提供することもできます。Countこれは、メソッドとを備えたDispinterfaceまたはDualインターフェイスを備えた単なるCOMオブジェクトItemです。デフォルトのメソッドとして、アイテムのdispid=0が必要です。ForEach構文をサポートするためにを提供_NewEnumすることもできます。DISPID_NEWENUM

于 2012-06-27T09:40:43.937 に答える