3

管理されていないサードパーティライブラリ(C)があります。C ++ / CLIでラッパーを作成しようとしているので、C#からライブラリを使用できます。Cの例がいくつかありますが、管理されていないヒープと管理されているヒープをブリッジする方法がわかりません。

ライブラリ内の関数の1つが構造体を返します。これは、マネージラッパーに保持する必要があります。この構造体は、他の関数のパラメーターとして使用されます。

動作中のC-例:

library.h

typedef struct FOO_BAR_STRUCT* FOO_BAR;
DLLEXPORT FOO_BAR FooBarCreate();

Example.c

#include <library.h>

int main(int argc, char* argv[]) {
char* address = "127.0.0.1"; 
FOO_BAR fb = NULL;

fb = FooBarCreate();

FooBarRegister(fb, address);
}

だから私のラッパーでは、例が何をするかを再現しようとしています。問題は構造体がどのヒープにあるかであることがわかりましたが、これを解決する方法を理解することができませんでした。

C#プロジェクトで使用するためにC ++ /CLI.dllとしてコンパイルされたC++コード。

FooBarComm.h

#include <library.h>

ref class FooBarComm
{
public:
    FooBarComm(char* address);
    ~FooBarComm();

private:
    FOO_BAR fb;
};

FooBarComm.cpp

#include "FooBarComm.h"

FooBarComm::FooBarComm(char* address)
{
    fb = FooBarCreate();
    FooBarRegister(fb, address);
}

FooBarComm::~FooBarComm()
{
}

そして、これは失敗します。アンマネージコードからマネージクラスにFOO_BAR構造体のインスタンスを取得し、それを後の関数の引数として使用するにはどうすればよいですか。

編集:

警告で失敗しますLNK4248:未解決のtyperefトークン(0100000D)
エラーLNK2028:未解決のトークン(0A00000A) "extern" C "struct FOO_BAR_STRUCT
エラーLNK2019:未解決の外部シンボル" extern "C" struct FOO_BAR_STRUCT

問題は、ライブラリに付属しているヘッダーファイルにFOO_BAR_STRUCTの定義がないことだと思います。私はこのライブラリが嫌いになり始めています。

構造体への参照を保持するアンマネージクラスを作成し、マネージクラスからこのアンマネージクラスを参照することは賢明ですか?

「通常の」C++クラスに変更すると、別のコンパイルエラーが発生します。

FooBarComm.h

#include <library.h>

#pragma unmanaged    
class FooBarComm {
...

コンパイルエラーが発生します:

エラーLNK2019:未解決の外部シンボル_FooBarCreateが参照されました

編集2:

もちろん、.libファイルへのリンクがありませんでした。

4

2 に答える 2

1

これは、サードパーティライブラリの.libファイルの省略によって引き起こされたリンカーエラーのように見えます。それをリンクオプションに追加すると、問題が解決することを期待しています。

于 2012-06-01T14:55:00.160 に答える
0

byte[]配列への明示的な変換の使用を検討してください。このようにして、構造体がどこにあるかを明示的に指定します。

Cでは次のようになります。

extern "C" void FooBarCreate(FooBar* Data);

extern "C" void FooBarUse(FooBar* Data)

C#では次のように記述します。

    [DllImport("SomeFile.dll")]
    public static extern void FooBarCreate_DLL([In,Out] byte[] BufForFOOBAR);

    [DllImport("SomeFile.dll")]
    public static extern void FooBarUSE_DLL([In,Out] byte[] BufForFOOBAR);


            /// Call DLL with managed struct
    public static Int32 FooBarUse_Managed(ManagedFooBar Value)
    {
        byte[] ValueBuffer = StructureToByteArray(Value);

        return FooBarUse_DLL(ValueBuffer);
    }

            /// Get value from native DLL to managed struct
    public static void FooBarCreate_Managed(ref ManagedFooBar Value)
    {
        byte[] ValueBuffer = new byte[Marshal.SizeOf(Value)];

        FooBarCreate_DLL(ValueBuffer);

        object TmpObj = new ManagedFooBar();

        ByteArrayToStructure(ValueBuffer, ref TmpObj);

        Value = (ManagedFooBar)TmpObj;
    }

ネイティブ関数はC#によって直接呼び出されます。

StructToByteArrayおよびByteArrayToStruct関数は次のとおりです。

using System.Runtime.InteropServices;
using System.Runtime.Serialization;


    public static byte[] StructureToByteArray(object obj)
    {
        int len = Marshal.SizeOf(obj);

        byte[] arr = new byte[len];

        IntPtr ptr = Marshal.AllocHGlobal(len);

        Marshal.StructureToPtr(obj, ptr, true);

        Marshal.Copy(ptr, arr, 0, len);

        Marshal.FreeHGlobal(ptr);

        return arr;
    }

    public static void ByteArrayToStructure(byte[] bytearray, ref object obj)
    {
        int len = Marshal.SizeOf(obj);

        IntPtr i = Marshal.AllocHGlobal(len);

        Marshal.Copy(bytearray, 0, i, len);

        obj = Marshal.PtrToStructure(i, obj.GetType());

        Marshal.FreeHGlobal(i);
    }

最後に、FooBarManaged(C#):

[Serializable]
    /// Sequential - make sure C does uses the same struct member alignment
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct FooBarManaged
{
    // Ususal POD field
    public Int32 ExpID;

    // Constant-sized string
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=128)]
    public byte[] FileName;
}

このコードについて話すことはあまりありません。ネイティブのsqlite3バックエンドをデータストレージとして使用するために、この種のマーシャリングに単純な自動生成機能を使用しました。したがって、Cとの間で多くの構造体をマーシャリングする必要があります。

于 2012-06-01T13:04:09.737 に答える