4

msdn http://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspxによると、「Platform Invocation Services (PInvoke) を使用すると、マネージ コードで DLL に実装されているアンマネージ関数を呼び出すことができます。 "

C++ で作成した DLL からいくつかのクラスをインポートしたいのですが
、可能ですか?

たとえば、DLL 内にいくつかの構造があります。

struct __declspec(dllexport) DLLVector3
{
    float x, y, z;
};

struct __declspec(dllexport) DLLQuaternion
{
    float x, y, z, w;
};

class __declspec(dllexport) DLLCharacter
{
public:
    DLLVector3 position;
    DLLQuaternion orientation;

    DLLCharacter()
    {

    }

    ~DLLCharacter()
    {

    }

    void setPosition(PxVec3 pos)
    {
        position.x = pos.x;
        position.y = pos.y;
        position.z = pos.z;
    }

    void setOrientation(PxQuat or)
    {
        orientation.x = or.x;
        orientation.y = or.y;
        orientation.z = or.z;
        orientation.w = or.w;
    }
};

struct __declspec(dllexport) PhysicalObject
{
    DLLCharacter *character;
    PxRigidActor *mActor;
    PxController *mController;
};

どの方法でそれらをインポートできますか? 特にポインタを持つ構造

4

2 に答える 2

6

アクセスのために C++ マネージ コードを記述する必要はありませんが、アンマネージ メモリとマネージ メモリの間を簡単に行き来することはできません。ここにいくつかの重要なポイントがあります 1) [StructLayout(LayoutKind.Sequential)] を使用して、C++ 構造体の上にマップする .net クラスを定義します

[StructLayout(LayoutKind.Sequential)]
[Serializable]
public struct SFVec3F : IRawStreamIO
{
    public double _x;
    public double _y;
    public double _z;
}

2) double、int32 などの基本的な型は、P/Invoke レイヤーを効率的に移動します - より複雑な型は、サンクの .net バリアントを獲得します - msft doco は、どのデータ型が効率的に移動するかをカバーし、それらを試して使用します

3) C++ ランドのポインターはすべて .net ランドの IntPtr であり、安全を確保したい場合はハンドルとして扱う必要があります。

4) ネイティブ C++ へのアクセスは非常に簡単です (Handle props は、もともとネイティブ C++ 側で供給された IntPtrs です)。

[DllImport("CS2V3.dll", CharSet = CharSet.Ansi)]
private static extern void AddChild(IntPtr csoPtr, IntPtr childPtr, short recomputeBounds, short adjustCoords, short blindchild);
public void AddChild(V3CSO theChild)
{
    AddChild(m_handle, theChild.Handle,0,0,0);
}

5) 文字列やその他の型では、.net で使用できる形式を取得するためにマーシャリングが必要です。これは、文字列をアンマネージ コードに渡すときに文字列に対して自動的に行われることに注意してください。

 [DllImport("CS2V3.dll", CharSet = CharSet.Ansi)]
private static extern IntPtr GetName(IntPtr csoPtr);
[DllImport("CS2V3.dll", CharSet = CharSet.Ansi)]
private static extern void SetName(IntPtr csoPtr, string newName);
   public string Name
    {
        get
        {
            IntPtr np = GetName(m_handle);
            return Marshal.PtrToStringAnsi(np);
        }
        set
        {
            SetName(m_handle, value);
        }
    }
于 2012-06-03T16:21:28.503 に答える
2

これは可能ですが、C++/CLI でラッパー コードを記述する必要があります。これにより、C#/.net コード (外部ではマネージ コード) から使用できるクラスを記述でき、実装では C++ コードを使用できます。

C++ クラスを直接インポートすることはできません。C スタイルの関数のみ。C スタイルの関数では、C プリミティブ型のみを渡すことができるため、相互運用が容易になります。一般に、C++ 以外のコードから C++ 型を正しく渡すことはほぼ不可能です。また、C++ オブジェクトを渡すことができない場合、通常、呼び出すことができる興味深い関数はほとんどありません。

後で編集: または、アンマネージ機能用の C スタイルのラッパー関数を作成することもできます。一度にすべてのパラメーターを渡す必要があります (構造体を渡すことができます) が、標準の C/C++ でラッパーを作成できます。

于 2012-06-03T16:02:26.297 に答える