从Java到c#通过JNI加载c# dll失败

本文关键字:加载 dll 失败 JNI 通过 Java | 更新日期: 2023-09-27 18:07:18

我正在为一个c#项目构建一个Java包装器。我用c++介于Java和c#之间。我的问题是,当我运行我的Java应用程序,我得到一个"无法加载文件或程序集'我的c# DLL,版本=1.0.0.0,文化=中性,PublicKeyToken=null'或它的依赖关系之一。系统找不到指定的文件。"如果我从c++中删除对c#代码的调用,就Java到c++的部分而言,事情加载得很好,但是当我试图调用c#时,dll无法加载。我创建了一个c++测试类,在包装c++代码的外部,尝试调用,从那里一切都很好。c# dll按预期加载并运行。所以我猜这是我的Java项目设置的问题,但我似乎找不到它。

我尝试使用进程监视器来确保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++ Code (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++ Code (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;
}

从Java到c#通过JNI加载c# dll失败

我在一年前遇到了同样的问题,原因很简单:java.exe找不到c# DLL,因为java.exe只在java.exe和system GAC的同一文件夹中搜索c# DLL。

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

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

  2. 签名你的c# DLL并使其强名称,然后安装到GAC

要了解java.exe如何搜索DLL,请使用Microsoft

中的procmon工具