开发者

C#和Java互相调用的方法小结

目录
  • C# 调用 Java 类和方法(IKVM / JNI-JNA 桥接)
    • 一、前置条件
    • 二、方法 1:使用 IKVM 桥接
      • 实现步骤:
      • 注意事项:
    • 三、方法 2:使用 JNI/JNA 桥接
      • 实现步骤:
      • 注意事项:
    • 四、常见问题
      • 五、高级特性
      • Java 调用 DLL 的类和方法(JNA)
        • 一、前置条件
          • 二、使用 JNA 方法
            • 实现步骤:
            • 注意事项:
          • 三、高级特性
            • 四、常见问题
            • 总结

              C# 调用 Java 类和方法(IKVM / JNI-JNA 桥接)

              一、前置条件

              1. 环境要求
                • IKVM:安装 IKVM 工具包(包含 ikvmcikvm 等工具),需要 JDK 和 .NET Framework。
                • JNI/JNA:需要 Java JDK(包含 javacjavah)和 .NET 的 P/Invoke 支持。
              2. 文件准备
                • Java JAR 包(如 example.lCkSojar)。
                • Java 类的完整定义(需公开目标类和方法)。

              二、方法 1:使用 IKVM 桥接

              原理:将 Java 字节码转换为 .NET 程序集(DLL),直接在 C# 中引用。

              实现步骤:

              • 安装 IKVM
                • 下载 IKVM 二进制包并解压,配置环境变量。
              • 转换 JAR 到 .NET DLL
              ikvmc -target:library example.jar -out:Example.dll
              
              • 在 C# 中引用 DLL
              using IKVM.Runtime;
              using java.example; // 对应 Java 包名
              
              public class Program {
                  public static void Main() {
                      // 调用 Java 类
                      ExampleClass obj = new ExampleClass();
                      obj.exampleMethod("Hello from C#");
                  }
              }
              

              注意事项:

              • 确保 Java 类和方法是 public 的。
              • 转换过程中可能丢失部分 Java 特性(如动态代理)。

              三、方法 2:使用 JNI/JNA 桥接

              原理:通过 JNI 调用 Java 虚拟机(JVM),C# 通过 P/Invoke 调用 JNI 接口。

              实现步骤:

              • 编写 Java 本地接口(JNI)
              public class NativeBridge {
                  public static native void callFromCSharp(Str编程ing message);
              }
              
              • 生成 C/C++ 头文件
              javac NativeBridge.java
              javah -jni NativeBridge
              
              • 生成 NativeBridge.h
              • 实现 C/C++ 桥接层
              #include <jni.h>
              #include "NativeBridge.h"
              
              JNIEXPORT void JNICALL Java_NativeBridge_callFromCSharp(JNIEnv *env, jclass cls, jstring msg) {
                  const char *cmsg = env->GetStringUTFChars(msg, 0);
                  printf("Java received: %s\n", cMsg);
                  env->ReleaseStringUTFChars(msg, cMsg);
              }
              
              • 编译为 DLL
              gcc -shared -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" NativeBridge.c -o NativeBridge.dll
              
              • C# 调用 DLL
              using System;
              using System.Runtime.InteropServices;
              
              public class Program {
                  [DllImport("NativeBridge.dll")]
                  private static extern void Java_NativeBridge_callFromCSharp(string message);
              
                  public static void Main() {
                      Java_NativeBridge_callFromCSharp("Hello via JNI");
                  }
              }
              

              注意事项:

              • 需要手动管理 JVM 生命周期(JNI_CreateJavaVM)。
              • 跨平台需重新编译 DLL/SO。

              四、常见问题

              1. IKVM 转换失败
                • 缺少依赖 JAR 包时,需添加 -reference:other.jar
              2. JNI 内存泄漏
                • 使用 ReleaseStringUTFChars 释放资源。
              3. DLL 路径问题
                • 确保 DLL 在输出目录或 PATH 环境变量中。

              五、高级特性

              1. IKVM 动态类加载
              var classLoader = new ikvm.runtime.AssemblyClassLoader(typeof(Program).Assembly);
              var clazz = classLoader.loadClass("java.example.DynamicClass");
              
              • JNI 回调 C# 方法
                • 在 C/C++ 层定义回调函数,通过 P/Invoke 调用 C# 委托。

              Java 调用 DLL 的类和方法(JNA)

              一、前置条件

              1. 环境要求
                • Java 8+,安装 JNA 库。
              2. 文件准备
                • 目标 DLL(如 NativeLib.dll)及其函数签名。

              二、使用 JNA 方法

              原理:通过 JNA 库直接映射 DLL 函数到 Java 接口,无需编写 C 代码。

              实现步骤:

              1. 添加http://www.devze.com JNA 依赖
              <!-- Maven -->
              <dependency>
                  <groupId>net.java.dev.jna</groupId>
                  <artifactId>jna</artifactId>
                  <version>5.13.0</version>
              </dependency>
              
              • 定义 Java 接口
              import com.sun.jna.Library;
              import com.sun.jna.Native;
              
              public interface NativeLib extehttp://www.devze.comnds Library {
                  NativeLib INSTANCE = Native.load("NativeLib", NativeLib.class);
                  
                  // 映射 DLL 函数
                  void exampleFunction(String message);
                  int addNumbers(int a, int b);
              }
              
              • 调用 DLL 函数
              public class Main {
                  public static void main(String[] args) {
                      NativeLib.INSTANCE.exampleFunction("Hello from Java");
                      int sum = NativeLib.INSTANCE.addNumbers(3, 4);
                      System.out.println("Sum: " + sum);
                  }
              }
              

              注意事项:

              • 函数名和参数类型需与 DLL 严格匹配。
              • 支持复杂类型(结构体、指针)需使用 Structure 类。

              三、高级特性

              回调函数

              public interface CallbackLib extends Library {
                  interface Callback extends CallbackProxy {
                      void invoke(String result);
                  }
                  void registerCallback(Callback callback);
              }
              

              结构体映射

              public class Point extends Structure {
                  public int x;
                  public int y;
              }
              

              四、常见问题

              1. UnsatisfiedLinkError
                • 检查 DLL 名称和路径,确保 32/64 位一致。
              2. 参数类型不匹配
                • 使用 Native.getNativeSize() 调试类型大小。

              总结

              • C# 调用 Java:优先使用 IKVM 简单场景,JNI 用于高性能需求。
              • Java 调用 DLL:JNA 是最简方案,无需编写 androidC 代码。
              • 代码可维护性:跨语言调用需详细文档记录接口约定。

              以上就是C#和Java互相调用的方法小结的详细内容,更多关于C#和Java互相调用的资料请关注编程客栈(www.devze.com)其它相关文章!

              0

              上一篇:

              下一篇:

              精彩评论

              暂无评论...
              验证码 换一张
              取 消

              最新开发

              开发排行榜