使用 JNI 将 C# 加载到 Java 项目时出现未解决的 link 错误

Unresolved link error using JNI to load C# into Java project

我正在尝试在我的 Java 项目中加载一个 DLL,以允许我使用 C# 中的一些代码。我做了一个示例并尝试在我的 Java 项目中实现它,但是当我尝试 运行 我的 Java 项目(设计器)时,我收到以下错误:

D:\RPMOpen\svnCobra\conversion\Designer>designer

D:\RPMOpen\svnCobra\conversion\Designer>java -jar Designer.jar "D:/RPMOpen/svnCobra"
Exception in thread "main" java.lang.UnsatisfiedLinkError: main/Designer.displayHeyLand()V
        at main.Designer.main(Designer.java:491)

我感到好奇的是,我在 Java 项目中收到有关加载 DLL 的错误,我设法修复了该错误,并且在 Java 项目的以下代码中 如果我注释掉最后一行,我的 Designer 现在可以正常工作了。这向我表明我的 .DLL 实际上正在正确加载,但我真的很困惑为什么我会收到 UnsatisfiedLinkError。

Java项目示例代码:

static {
        System.load("D://RPMOpen/svnCobra/Java/Designer/HeyLand.dll");
        }

    public native void displayHeyLand();

    public static void main(String[] args)
    {
        if (args.length == 0)
        {
            throw new IllegalArgumentException("Conversion location required");
        }



    cobraLocation = args[0];
            INPUT = cobraLocation + "/conversion/src/vb/";
            OUTPUT = cobraLocation + "/conversion/aui/Designer/";
            //System.loadLibrary(cobraLocation + "/conversion/Designer/GetFRXWrapper.dll");
            //String s = getFromFRX();
            //System.out.println(s);

            Designer t = new Designer();
            t.displayHeyLand();

试图实现的原始 C# 代码:

using System;
using System.Windows.Forms;

public class CSharpHeyLand
{
    public CSharpHeyLand() { }

    public void displayHeyLand()
    {
        MessageBox.Show("Hey Java, this is C#!", "Sample");
    }
 }

来自我的包装器的元素,包括一个 C++ 源文件和两个头文件:

 //Cpp file HeyLand.cpp *******************************************

#include <jni.h>
#include "Java\HeyWork.h"



// managed c++ header containing call to c#
#include "MCPP\HeyLand.h"

// JNI call to managed C++ Class

JNIEXPORT void JNICALL Java_Main_Designer_displayHeyLand  (JNIEnv *jn, jobject jobj) {

    // istantiate the MC++ class.
    HeyLandC* t = new HeyLandC();

    // actual call is made. 
    t->callCSharpHeyLand();
}

//Header file HeyWork.h *******************************************

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

#ifndef _Included_Designer
#define _Included_Designer
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Designer
 * Method:    displayHeyLand
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_Main_Designer_displayHeyLand
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

//Header file HeyLand.h *******************************************

#using <mscorlib.dll>
#using "/CSharpHeyLand.netmodule"

using namespace System;

public __gc class HeyLandC
{
    public:
        // provide .NET interop and garbage collecting to the pointer
        CSharpHeyLand __gc *t;
        HeyLandC() {
            t = new CSharpHeyLand();
            // Assign the reference a new instance of the object
        }

     // This inline function is called from the C++ Code
        void callCSharpHeyLand() {
            t->displayHeyLand();
        }
};

非常感谢任何帮助!

几个月前我遇到了同样的错误。我们尝试使用来自 Java 的 C# DLL,这是我们所做的:

  1. 编写 C# DLL。
  2. 开发一个C++/CLI DLL作为C# DLL的包装器,导出需要的函数。
  3. 在Java中,加载C++/CLI DLL并通过JNI调用函数。

加载C++/CLI DLL已经OK,就像你的情况一样,在执行某些代码时,遇到UnsatisfiedLinkError错误,我们用Process Monitor跟踪它,这是因为java exe 未找到引用 C# 程序集。

与本机 C++ DLL 不同,引用的托管程序集不会在 exe 启动时立即加载,it is loaded as needed, this happens when the JIT compiler 在应用程序 运行 代码第一次到达时将 MSIL 代码转换为本机代码时间。这解释了当它到达该行代码时发生错误的时间。

所以要弄清楚这个问题,您可以使用进程监视器来监视 java.exe 以查看它是如何加载 DLL 的。据我观察,java exe 将尝试在以下位置找到 C# DLL:

  1. global assembly cache.(GAC) 中排名第一。 GAC 中只有强名称程序集。
  2. java.exe的文件夹。

所以如果引用程序集不在这两个地方,你就会遇到那个错误。

您还可以创建一个 DEVPATH 环境变量来引用托管 DLL 的存储位置。在这种情况下,您必须设置 developmentMode on at machine.config file.