试图传入一个用户提供的字符串,该字符串有一个到jvm.dll的路径,但它不会加载库,除非我用以下硬代码:
#define RUNTIME_DLL _T("C:\Program Files\Java\jre7\bin\Server\jvm.dll")
如果我尝试以下操作,它会编译但失败:
HINSTANCE handle = LoadLibrary((const char*)Marshal::StringToHGlobalAnsi(string).ToPointer());
"string"var具有与_T()完全相同的复制粘贴路径,但仍然失败。不是C/C++方面的专家,所以我不确定是什么_T()让它起作用。
更新:
尝试过这个:
// System::String always stored as Unicode, get a Unicode pointer with no conversion necessary
pin_ptr<const WCHAR> lib_name = PtrToStringChars(string);
// Always use the Unicode version of LoadLibrary
HINSTANCE handle = LoadLibraryW(lib_name);
但是它仍然不会加载jvm.dll文件。只有当我这样做时,它才会加载:
#define RUNTIME_DLL _T("C:\Program Files\Java\jre7\bin\Server\jvm.dll")
// System::String always stored as Unicode, get a Unicode pointer with no conversion necessary
pin_ptr<const WCHAR> lib_name = PtrToStringChars(RUNTIME_DLL);
// Always use the Unicode version of LoadLibrary
HINSTANCE handle = LoadLibraryW(lib_name);
也尝试过:
// System::String always stored as Unicode
marshal_context^ ctx = gcnew marshal_context();
pin_ptr<const WCHAR> lib_name = PtrToStringChars(jvmDllPath);
//const wchar_t * lib_name = ctx->marshal_as<const wchar_t*, System::String^>(jvmDllPath);
printf("JVM Path: %s", lib_name);
// Always use the Unicode version of LoadLibrary
handle = LoadLibraryW(lib_name);
if( handle == 0) {
printf("Failed to load jvm dll n");
//printf(ErrorExit((LPTSTR)(const char*)"Initialize"));
// this is the part that will work
System::String^ string = gcnew System::String("C:\Program Files\Java\jre7\bin\Server\jvm.dll");
pin_ptr<const WCHAR> lib_name = PtrToStringChars(string);
handle = LoadLibraryW(lib_name);
}
delete ctx; // do this for now to not create memory leaks
C++/CLI方法签名为:
void Initialize(String^ jvmDllPath)
正文基本上就是上面的代码
用字符串参数调用这个的C#代码是这样的:
obj.Initialize("c:\program files\java\jdk7\jre\bin\server\jvm.dll");
从Ben的建议中提供答案,这样人们/新手和临时的c/c++/cli程序员就可以找到一个快速的答案来避免我所经历的:
const char * CliToNativeString(String^ cliString){
const char * converted;
converted = (gcnew marshal_context())->marshal_as<const char *>( cliString );
return converted;
}
String^ NativeToCliString(const char * nString){
String^ converted = gcnew String("");
if(nString != NULL)
converted = (gcnew marshal_context())->marshal_as<String^>(nString);
return converted;
}
从System::String^
中获取C样式字符串有更好的方法。查看VC++提供的marshal_as
和marshal_context
模板。
这里的直接问题是,您正在为Unicode进行编译,因此LoadLibrary
需要Unicode字符串,但StringToHGlobalAnsi
不返回Unicode字符串。再多的指针投射也不会改变所指向字符串的编码。
您还存在内存泄漏。
试试这个:
#include <vcclr.h>
// System::String always stored as Unicode, get a Unicode pointer with no conversion necessary
pin_ptr<const WCHAR> lib_name = PtrToStringChars(string);
// Always use the Unicode version of LoadLibrary
HINSTANCE handle = LoadLibraryW(lib_name);
如果这是有效的,而上面没有,那么从C#发送的字符串有问题:
System::String^ string = gcnew System::String(L"C:\Program Files\Java\jre7\bin\Server\jvm.dll");
pin_ptr<const WCHAR> lib_name = PtrToStringChars(string);
HINSTANCE handle = LoadLibraryW(lib_name);