0
デリゲートを関数ポインタにマーシャリングしようとしています。デリゲートの戻り値の型は文字列の配列で、関数ポインタの戻り値の型はchar **'値を整列化できません:無効な管理対象/非管理対象型の組み合わせです。'文字列配列のデリゲートを整列化しています。
以下のコードは無効な管理対象/非管理型の組み合わせの例外をスローします。これをどうすれば解決できますか?
// unmanaged code
typedef char** (*MyFuncPtr)(void);
class __declspec(dllexport) MyUnmanagedClass{
private:
MyFuncPtr mFunPtr
public:
MyUnmanagedClass(MyFuncPtr funPtr)
{
mFunPtr = funPtr;
}
char* Func1()
{
// callback
mFunPtr();
return "something";
}
};
// managed wrapper (CLI)
public delegate cli::array<String^>^ MyDelegate();
public class MyCliClass{
private:
MyDelegate mDel;
public:
MyCliClass(MyDelegate del)
{
mDel = del;
}
String^ Func2()
{
MyFuncPtr funPtr = static_cast<MyFuncPtr>(Marshal::GetFunctionPointerForDelegate(mDel).ToPointer());
MyUnmanagedClass* muc = new MyUnmanagedClass(funPtr);
char* retValPtr = muc->Func1();
return context->marshal_as<String^>(retValPtr);
}
};
// managed client (C#)
class Program
{
static void Main(string[] args)
{
MyCliClass mcc = new MyCliClass(Func3);
mcc.Func2();
}
static string[] Func3()
{
return new[] { "Some 1", "Some 2" };
}
}
です。呼び出し元は、返された配列内の要素数と、文字列と配列の記憶領域を解放する必要があるかどうかを知ることはできません。例外は、単にマーシャルがどちらも知らないことを伝えます。それは分からない。あなたはこれを再考する必要があります。 –
その場合、これを達成するために他にどのような選択肢が必要ですか? –
自分自身に 'GetFunctionPointerForDelegate'を避けるという目標を設定します。 C++/CLIコードでは、C++関数とC#関数の両方を呼び出し、C++オブジェクトとC#オブジェクトの両方に直接アクセスできるため、C++/CLIではその必要はありません。だからあなたが必要とするのは、正しい呼び出しシグネチャを持つC++/CLI関数です。ポインタを取り、すぐに正しい型(キャストなし)を得ることができます。その関数の中で、C#オブジェクトにアクセスし、代理人を呼び出すことができます。 –