我正在寻找灵活的方法来编写我自己的DLL并访问使用C ++ / CLI在C ++中处理的DLL。我是InterOp和Reflection的新手,特别是在使用DefinePInvokeMethod时,将StringBuilder封送到一个带有参数char *(代码中的helloc)的入口点的DLL函数。 IJW处理入口点在直接调用dll时使用std :: string的情况,但是当我还尝试使用DefinePInvokeMethod将StringBuilder封送到std :: string时,为什么会有TargetInvocationExceptions。为什么IJW工具在这种情况下不知道构造一个std :: string?被调用者不是负责在非托管端构造字符串吗?以下是工作代码。有人请帮助我通过它的改编,以便也可以通过DefinePInvokeMethod访问hellos(std :: string)?
native.dll
//Both methods just std::cout << greeting;
extern "C" DLL void helloc(char* greeting);
extern "C" DLL void hellos(std::string greeting)
Test.cpp的
void pinvoketest()
{
// Create the AssemblyBuilder.
AssemblyName^ asmName = gcnew AssemblyName("PInvokeTest");
AssemblyBuilder^ dynamicAsm = AppDomain::CurrentDomain->DefineDynamicAssembly(
asmName,
AssemblyBuilderAccess::RunAndSave
);
// Create the module.
ModuleBuilder^ dynamicMod =
dynamicAsm->DefineDynamicModule(asmName->Name, asmName->Name + ".dll");
TypeBuilder^ tb = dynamicMod->DefineType(
"MyType",
TypeAttributes::Public | TypeAttributes::UnicodeClass
);
MethodInfo^ mi;
try
{
MethodBuilder^ mb = tb->DefinePInvokeMethod(
"helloc",
"native.dll",
"helloc",
MethodAttributes::Public | MethodAttributes::Static | MethodAttributes::PinvokeImpl,
CallingConventions::Standard,
void::typeid,
gcnew array<Type^>{StringBuilder::typeid},
CallingConvention::Cdecl,
CharSet::Ansi);
mb->SetImplementationFlags(
mb->GetMethodImplementationFlags() | MethodImplAttributes::PreserveSig);
Type^ t = tb->CreateType();
mi = t->GetMethod("helloc");
Console::WriteLine("Testing PInvoke method...");
mi->Invoke(nullptr, gcnew array<Object^>{gcnew StringBuilder("This is a test greeting")});
char x;
std::cin >> x;
}
catch (TargetInvocationException^ ex)
{
Console::WriteLine(ex->InnerException);
char x;
std::cin >> x;
}
catch (Exception^ ex)
{
Console::WriteLine(ex);
char x;
std::cin >> x;
}
};