通过JNI从Java到C#无法加载C#dll

时间:2016-09-15 17:20:02

标签: java c# c++ java-native-interface

我正在围绕C#项目构建Java包装器。我使用C ++进入Java和C#之间。我的问题是,当我运行我的Java应用程序时,我得到了一个"无法加载文件或程序集' MyC#DLL,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null&#39 ;或其中一个依赖项。系统找不到指定的文件。"错误。如果我将C ++中的调用删除到C#代码就可以加载,就Java到C ++部分而言,但是当我尝试调用C#时dll无法加载。我在包装器C ++代码外部创建了一个C ++测试类来尝试调用,从那里一切正常。 C#DLL加载并按预期运行。所以我猜测我的Java项目设置存在问题,但我似乎无法找到它。

我尝试使用Process Monitor来确保C#dll没有加载而且它不是。 c ++包装器确实正确加载。

我的Java代码是从项目文件夹执行的,但其他所有内容(C ++和C#)都在同一目录中。任何帮助表示赞赏。

Java代码:

public final class MyClass{

static {
    try
    {
        System.load("C:\\Dir\\CppBridge.dll");
    }
    catch(Exception e)
    {
        System.out.println("-!-!- Error loading library -!-!-");
    }

}

private static native String getXML();

public static List<Site> getXMLFromC#()
{
    String xml = MyClass.getXML();
}}

C ++代码(Methods.h):

public ref class Wrapper
{
    public: MyPackage::C#Project^ api;
    public: Wrapper()
    {
        api = gcnew MyPackage::C#Project;
    }

    public: char* getXML()
    {
        char* error;
        try
        {
            System::String^ xml = api->getXML();
            return (char*)Marshal::StringToHGlobalAnsi(xml).ToPointer();
        }
        catch (Exception^ e)
        {
            char* error = (char*)Marshal::StringToHGlobalAnsi("Error:" + e->Message).ToPointer();
        }
        return error;
    }
};

C ++代码(CppBridge.h)

#include <jni.h>
/* Header for class MyC#Class*/

#ifndef _Included_MyC#Class
#define _Included_MyC#Class
#ifdef __cplusplus
extern "C" {
#endif
    /*
    * Class:     MyC#Class
    * Method:    getUserSites
    * Signature: String, String, String, String, String, boolean
    */
    JNIEXPORT jstring JNICALL Java_MyPackage_getXML(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

C ++代码(CppBridge.cpp)

using namespace System::Runtime::InteropServices; //Marshal

class CppBridge
{
    public: CppBridge() {};
};

JNIEXPORT jstring JNICALL Java_MyPackage_getXML(JNIEnv *jn, jobject jobj)
{
    jstring error;
    try
    {
        Methods::Wrapper^ wrapper = gcnew Methods::Wrapper();
        char* xml = wrapper->getXML();
        jstring result = jn->NewStringUTF(xml);
        return result;
    }
    catch (Exception^ e)
    {
        char* result = (char*)Marshal::StringToHGlobalAnsi("Source: "+ e->Source + " | Message: " + e->Message).ToPointer();
        error = jn->NewStringUTF(result);
    }
    return error;
}

1 个答案:

答案 0 :(得分:3)

我在一年前遇到同样的问题,原因很简单:java.exe无法找到C#DLL,因为java.exe只搜索java.exe和系统的同一文件夹中的C#DLL GAC

所以解决这个问题,有两种方式:

  1. 将您的C#DLL及其依赖项放在java.exe的同一文件夹中

  2. 签署您的C#DLL并使其成为强名称,然后将其安装到GAC

  3. 要了解java.exe如何搜索DLL,请使用Microsoft的工具procmon