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

 更新时间:2025年04月02日 09:34:42   作者:老胖闲聊  
这篇文章主要介绍了C#和Java互相调用的方法,文中展示了如何在不同编程语言之间实现互操作,每种语言之间的互操作都有其特定的方法和工具,希望这些示例能够帮助你更好地理解和实现跨语言调用,需要的朋友可以参考下

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

一、前置条件

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

二、方法 1:使用 IKVM 桥接

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

实现步骤:

  • 安装 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(String 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. 环境要求
  2. 文件准备
    • 目标 DLL(如 NativeLib.dll)及其函数签名。

二、使用 JNA 方法

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

实现步骤:

  1. 添加 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 extends 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 是最简方案,无需编写 C 代码。
  • 代码可维护性:跨语言调用需详细文档记录接口约定。

以上就是C#和Java互相调用的方法小结的详细内容,更多关于C#和Java互相调用的资料请关注脚本之家其它相关文章!

相关文章

  • c# wpf如何附加依赖项属性

    c# wpf如何附加依赖项属性

    这篇文章主要介绍了c# wpf如何附加依赖项属性,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下
    2021-03-03
  • 10个被低估的C#性能优化技巧分享

    10个被低估的C#性能优化技巧分享

    这篇文章主要为大家详细介绍了10个被低估的C#性能优化技巧,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以参考一下
    2025-03-03
  • C#自动化生成PowerPoint(PPT)演示文稿

    C#自动化生成PowerPoint(PPT)演示文稿

    在当今快节奏的商业环境中,演示文稿是信息传递和沟通的关键工具,下面我们就深入探讨如何利用C#和 Spire.Presentation for .NET实现从零开始创建,编辑和保存PowerPoint演示文稿吧
    2025-11-11
  • C#多播委托的实现示例

    C#多播委托的实现示例

    C#中的多播委托是一种特殊的委托类型,可以持有多个方法的引用,并在调用时依次执行这些方法,本文就来介绍一下C#多播委托的实现示例,感兴趣的可以了解一下
    2025-12-12
  • .NET MemoryCache如何清除全部缓存

    .NET MemoryCache如何清除全部缓存

    本文主要介绍了.NET MemoryCache如何清除全部缓存,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • 在Form_Load里面调用Focus无效的解决方法

    在Form_Load里面调用Focus无效的解决方法

    在调用Form_Load的时候,Form其实还没有进入展示阶段,自然Focus()调用也就没效果了。
    2013-02-02
  • C#中Path类的使用方法

    C#中Path类的使用方法

    这篇文章主要介绍了C#中Path类的使用方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • vs代码段快捷键设置(图文)

    vs代码段快捷键设置(图文)

    学习代码快捷键是程序员必学知识点,会使用代码快捷在程序开发过程中会提高开发效率,下面小编给大家整理些有关vs代码段快捷键设置的技巧,需要的朋友可以参考下
    2015-08-08
  • 浅谈对c# 面向对象的理解

    浅谈对c# 面向对象的理解

    这篇文章主要介绍了个人对c# 面向对象的理解,算是一个入门篇吧,给需要的小伙伴参考下,抛砖引玉。
    2014-12-12
  • C#中ListView用法实例

    C#中ListView用法实例

    我们经常会在应用程序中使用列表的形式来展现一些内容,所以学好ListView是非常必需的,下面这篇文章主要给大家介绍了关于C#中ListView用法的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-06-06

最新评论