C#和Java互相调用的方法小结
目录
- C# 调用 Java 类和方法(IKVM / JNI-JNA 桥接)
- 一、前置条件
- 二、方法 1:使用 IKVM 桥接
- 实现步骤:
- 注意事项:
- 三、方法 2:使用 JNI/JNA 桥接
- 实现步骤:
- 注意事项:
- 四、常见问题
- 五、高级特性
- Java 调用 DLL 的类和方法(JNA)
- 一、前置条件
- 二、使用 JNA 方法
- 实现步骤:
- 注意事项:
- 三、高级特性
- 四、常见问题
- 总结
C# 调用 Java 类和方法(IKVM / JNI-JNA 桥接)
一、前置条件
- 环境要求:
- IKVM:安装 IKVM 工具包(包含
ikvmc
、ikvm
等工具),需要 JDK 和 .NET Framework。 - JNI/JNA:需要 Java JDK(包含
javac
、javah
)和 .NET 的 P/Invoke 支持。
- IKVM:安装 IKVM 工具包(包含
- 文件准备:
- Java JAR 包(如
example.lCkSojar
)。 - Java 类的完整定义(需公开目标类和方法)。
- Java JAR 包(如
二、方法 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。
四、常见问题
- IKVM 转换失败:
- 缺少依赖 JAR 包时,需添加
-reference:other.jar
。
- 缺少依赖 JAR 包时,需添加
- JNI 内存泄漏:
- 使用
ReleaseStringUTFChars
释放资源。
- 使用
- DLL 路径问题:
- 确保 DLL 在输出目录或
PATH
环境变量中。
- 确保 DLL 在输出目录或
五、高级特性
- 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)
一、前置条件
- 环境要求:
- Java 8+,安装 JNA 库。
- 文件准备:
- 目标 DLL(如
NativeLib.dll
)及其函数签名。
- 目标 DLL(如
二、使用 JNA 方法
原理:通过 JNA 库直接映射 DLL 函数到 Java 接口,无需编写 C 代码。
实现步骤:
- 添加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; }
四、常见问题
- UnsatisfiedLinkError:
- 检查 DLL 名称和路径,确保 32/64 位一致。
- 参数类型不匹配:
- 使用
Native.getNativeSize()
调试类型大小。
- 使用
总结
- C# 调用 Java:优先使用 IKVM 简单场景,JNI 用于高性能需求。
- Java 调用 DLL:JNA 是最简方案,无需编写 androidC 代码。
- 代码可维护性:跨语言调用需详细文档记录接口约定。
以上就是C#和Java互相调用的方法小结的详细内容,更多关于C#和Java互相调用的资料请关注编程客栈(www.devze.com)其它相关文章!
精彩评论