2012-04-05 148 views
1

嘗試傳遞用戶提供的字符串,該字符串具有jvm.dll的路徑,但它不會加載該庫,除非我用硬編碼以下內容:C++/CLI LoadLibrary無法將System :: String轉換爲LPCWSTR和const char *

#define RUNTIME_DLL _T("C:\\Program Files\\Java\\jre7\\bin\\Server\\jvm.dll") 

它編譯但未能如果我試試這個:

HINSTANCE handle = LoadLibrary((const char*)Marshal::StringToHGlobalAnsi(string).ToPointer()); 

的「弦」變種具有完全相同的副本和_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#代碼調用這與一個stri NG參數是這樣的:

obj.Initialize("c:\\program files\\java\\jdk7\\jre\\bin\\server\\jvm.dll"); 

這裏提供了答案來自Ben的建議,所以人們/ newbs和臨時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; 
    } 
+0

我也取代了(常量char *)與(LPCWSTR)一起施放,它編譯但仍然失敗....非常奇怪。 – bbqchickenrobot 2012-04-05 01:34:09

+0

是的,鑄造將強制你的代碼進行編譯。這並沒有說明它的正確性,甚至不需要它有任何意義。如果您編寫的代碼不起作用,請首先消除*全部*強制轉換,然後執行編譯器發出的錯誤診斷。 – 2012-04-05 02:27:10

+0

我知道,但因爲使用C++/CLI鑄造是必需的,所以不是這樣。不過謝謝。 – bbqchickenrobot 2012-04-05 02:42:54

回答

3

有是從System::String^獲取C風格字符串的更好方法。查看隨VC++提供的marshal_asmarshal_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); 
+0

感謝您的幫助,嘗試了您的方法,它也有同樣的問題。我也嘗試過更新後的方法。非常怪異的IMO。 – bbqchickenrobot 2012-04-05 02:56:22

+0

@bbqchickenrobot:你還有哪些問題?它是編譯錯誤(顯示消息)還是運行時錯誤? 'string'的價值是什麼? – 2012-04-05 03:01:46

+0

順便說一句,'_T'可以是ANSI字符串,也可以是Unicode字符串,具體取決於您的編譯設置。既然你正在編譯Unicode,'L「jvm.dll」'會給你同樣的效果。實際上,在字符串中沒有任何雙反斜槓,只有在生成字符串的代碼中才有? – 2012-04-05 03:04:42

相關問題