You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在非Xamarin/Mono的Java Android项目中调用C# DLL的技术问询

在Android Java项目中调用C# DLL的解决方案与疑问解答

先明确你的场景:你想在纯Java开发的Android项目里调用C# DLL,最初的方案是用DllExport把C#转成C可调用的DLL再打包成.so,但遇到了C代码依赖windows.h的问题,下面针对你的两个疑问逐一拆解:

疑问1:如何不依赖windows.h来使用DllExport生成的DLL?

DllExport生成的是标准C兼容的导出函数,并非只能在Windows环境下使用。Android基于Linux内核,我们可以用POSIX标准的动态链接库操作函数替代Windows的LoadLibrary和GetProcAddress——这些函数定义在dlfcn.h头文件里,完全不需要windows.h。

修改后的Android兼容C++调用代码

#include <dlfcn.h>
#include <iostream>

// 定义与C#导出函数匹配的函数指针类型
typedef int(*GetRandomEvenNumber)();

int main() {
    // 加载Android平台的动态库(注意路径是.so文件,比如./libmycsharp.so)
    void* lib = dlopen("libmycsharp.so", RTLD_LAZY);
    if (!lib) {
        std::cerr << "无法加载库: " << dlerror() << std::endl;
        return 1;
    }

    // 获取导出函数的地址
    dlerror(); // 清除之前的错误状态
    GetRandomEvenNumber getRndNumber = (GetRandomEvenNumber)dlsym(lib, "GetRandomEvenNumber");
    const char* err = dlerror();
    if (err) {
        std::cerr << "无法找到函数: " << err << std::endl;
        dlclose(lib);
        return 1;
    }

    // 调用C#导出的函数
    int c = getRndNumber();
    std::cout << "生成的随机偶数: " << c << std::endl;

    // 释放动态库资源
    dlclose(lib);
    return 0;
}

编译注意事项

编译这段代码时,需要链接POSIX动态链接库,添加-ldl参数,比如:

g++ -o test_csharp_call test_csharp_call.cpp -ldl

另外,你需要把DllExport生成的DLL交叉编译成对应Android架构的.so文件(比如armeabi-v7a、arm64-v8a),确保和你的Android项目架构匹配。

疑问2:是否可以使用.NET Core 2.0来实现该需求而无需使用DllExport?

很遗憾,.NET Core 2.0无法直接满足这个需求,原因有两点:

  1. .NET Core 2.0的核心支持平台是Windows、Linux桌面和服务器,对Android的原生支持几乎为零,没有官方工具链能把它的代码编译成Android可调用的.so库。
  2. .NET Core 2.0没有类似[UnmanagedCallersOnly]的特性(该特性在.NET 5+引入),无法直接导出可被原生代码调用的函数,仍然需要依赖DllExport这类第三方工具生成兼容的导出符号。

更优替代方案(升级.NET版本)

如果可以升级到.NET 6及以上的版本(比如用.NET for Android),你完全可以抛弃DllExport:

  1. 在.NET项目中用[UnmanagedCallersOnly(EntryPoint = "GetRandomEvenNumber")]标记要导出的静态函数,替代DllExport。
  2. 通过.NET的AOT编译功能,直接将C#代码编译成Android对应的.so原生库。
  3. 最后在Android的C层(JNI)调用这个.so的导出函数,再让Java层通过JNI调用C代码。

举个修改后的C#代码示例(.NET 6+):

namespace NumbersLibCS {
    public static class Math {
        [UnmanagedCallersOnly(EntryPoint = "GetRandomEvenNumber")]
        public static int GetRandomEvenNumber() {
            var rnd = new Random();
            int n = rnd.Next(1, 1000 ) * 2;
            return n;
        }
    }
}

然后用.NET发布命令编译成Android原生库:

dotnet publish -r android-arm64 -c Release

这样生成的.so库可以直接被Android的C++代码调用,无需额外的包装层。


内容的提问来源于stack exchange,提问作者S.A.Parkhid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 09:02:36