2014-02-13 46 views
0

當C#COM未使用帶有codebase選項的regasm註冊時,通過JNI-C++/CLI從Java到C#的函數調用失敗。我已按照P2: Calling C# from Java中的說明進行了一些示例修改。對C#COM的Java JNI調用失敗,當COM註冊時沒有regasm的代碼庫選項

頭兒:C#

通過創建一個接口,IRunner,以及製備該庫組件COM可見更改C#DLL到COM。

namespace RunnerCOM 
{ 
    public interface IRunner 
    { 
     String ping(); 
    } 
    public class Runner:IRunner 
    { 
     static void Main(string[] args) 
     { 
     } 
     public Runner() { } 
     public String ping() 
     { 
      return "Alive (C#)"; 
     } 
    } 
} 

NÚMERO原因:Java的 否Java部分所做的更改。

NÚMEROTRE:C++

這部分改爲創建RunnerCOM.Runner類的新實例,並使用該結果。下面是關於如何從非託管代碼調用託管代碼一個很好的教程:http://support.microsoft.com/kb/828736

#include "stdafx.h" 
#include "Runner.h" 
#pragma once 
#using <mscorlib.dll> 
#import "RunnerCOM.tlb" 

JNIEXPORT jstring JNICALL Java_Runner_ping(JNIEnv *env, jobject obj){ 
    RunnerCOM::IRunnerPtr t = RunnerCOM::IRunnerPtr("RunnerCOM.Runner"); 
    BSTR ping = t->ping(); 

    _bstr_t temp(ping, true); 

    char cap[128]; 
    for(unsigned int i=0;i<temp.length();i++){ 
     cap[i] = (char)ping[i]; 
    } 

    return env->NewStringUTF(cap); 
} 

現在我的問題,

  1. 上面的代碼失敗並_com_error異常,類沒有註冊(0x80040154的),除非在註冊RunnerCOM.dll期間啓用代碼庫選項與regasm.exe。爲什麼是這樣?如果代碼不是從JNI運行的,我將它作爲一個exe文件進行測試,它工作正常。 RunnerCOM.dll只是在工作目錄中找到的。
  2. 類型鑄造_bstr_t tempchar*失敗。例如,char *out = (char*) temp;與上面的問題類似,當它作爲exe被構建和執行時,它工作正常,但是當它是JNI調用時會使JVM崩潰。

通過這種方式就是我用來運行它作爲一個可執行:

int main(){ 
    RunnerCOM::IRunnerPtr t = RunnerCOM::IRunnerPtr("RunnerCOM.Runner"); 
    BSTR ping = t->ping(); 

    _bstr_t temp(ping, false); 

    printf(temp); 
    return 0; 
} 

回答

0
  1. 代碼庫在註冊表中創建一個Codebase項。 Codebase條目指定了未安裝在全局程序集緩存中的程序集的文件路徑,因此,當您指定代碼庫時,系統將根據路徑找到DLL。如果沒有,它會嘗試在GAC和當前工作目錄中找到dll。在JNI中,我認爲當前的工作目錄不是DLL所在的文件夾。您可以使用process explorer來查找當前的工作目錄,也可以使用process monitor來查找exe正在查找哪些目錄以查找dll。

  2. 將_bstr_t轉換爲char *,char *字符串上限不以'\ 0'結尾的代碼,我認爲這可能會導致JNI中的問題。使用_bstr_t運算符(char *),可以從_bstr_t對象獲取以空字符結尾的字符串。詳情請查閱msdn example

您提到C++/CLI,C++/Cli和COM warpper是與C#代碼互操作的兩種不同方法。如果您使用C++/CLI作爲橋接器,則不需要將C#DLL註冊爲COM,請參閱:Calling .Net Dlls from Java code without using regasm

如果您使用的是COM,則應該先撥打CoInitialize()來首先在代碼中初始化COM。

+0

我正在尋找更具體的答案與參考。例如,我已經做了與問題1相同的假設。它在加載期間查找system32文件夾中的dll,但工作目錄已正確初始化(只是不知道爲什麼它看起來不存在)。對於第二個答案,_bstr_t到char *的轉換應該如我所描述的那樣工作。感謝其他點,但。 – user845279

相關問題