003 - C++ CSharp Java 调用 C++ DLL

C++ CSharp Java 调用 C++ DLL

导出C++ Dll

C++编译器为VS2019

64为的Debug模式生成的无法调用(不知道具体原因)

C++导出函数接口的方式主要有两种:

_stdcall可以在项目属性 -> C/C++ -> 高级 -> 调用约定处指定,就不用在每个函数前指定了

在函数定义时候加extern “C” _declspec(dllexport)

exportdll.h

extern "C" _declspec(dllexport) int _stdcall Add(int i, int j);
extern "C" _declspec(dllexport) float _stdcall Avg(int i, int j);

exportdll.cpp

#include "exportdll.h"

int Add(int i, int j)
{
    return i + j;
}

float Avg(int i, int j)
{
    return (i + j) / 2.0f;
}

使用模块定义文件(.def)声明

exportdll.h

int _stdcall Add(int i, int j);
float _stdcall Avg(int i, int j);

exportdll.cpp

#include "exportdll.h"

int Add(int i, int j)
{
    return i + j;
}

float Avg(int i, int j)
{
    return (i + j) / 2.0f;
}

右键源文件,选择添加模块定义文件exportdll.def

在项目属性 -> 链接器 -> 输入 -> 模块定义文件处输入exportdll.def

exportdll.def

LIBRARY	exportdll
EXPORTS
    Add
    Avg

CMake+MinGW好像不能使用def,只需要加上extern “C”

简单调用C++ DLL

均为基本数据类型的调用,复杂的数据类型会涉及到转换对应关系

C++动态调用

_stdcall也可以在项目属性 -> C/C++ -> 高级 -> 调用约定处指定

第五行可能会出错E0167 “const char *” 类型的实参与 “LPCWSTR” 类型的形参不兼容,项目属性 -> 高级 -> 字符集选择"使用多字节字符集”

// MinGW注意头文件手动指定为Windows.h
int main()
{
    typedef int(_stdcall *AddFun)(int, int);
    typedef float(_stdcall *AvgFun)(int, int);
    HINSTANCE dll = LoadLibrary("exportdll.dll");
    if (dll != NULL)
    {
        AddFun Add = (AddFun) GetProcAddress(dll, "Add");
        if (Add != NULL)
        {
            cout << Add(3, 4) << endl;
        }
        AvgFun Avg = (AvgFun) GetProcAddress(dll, "Avg");
        if (Avg != NULL)
        {
            cout << Avg(3, 4) << endl;
        }
    }
    return 0;
}

C#调用

CallingConvention为StdCall可以不用指定

class Program
{
    [DllImport("exportdll.dll", CallingConvention = CallingConvention.StdCall)]
    public static extern float Avg(int left, int right);
    [DllImport("exportdll.dll"]
    public static extern int Add(int left, int right);
    static void Main(string[] args)
    {
        Console.WriteLine(Avg(11, 2));
        Console.WriteLine(Add(11, 2));
    }
}

Java调用

Java调用C++主要有三种方法:

1. JNI

性能最高,这里不做阐述

2. JNative

DllImport.java

public class DllImport {
    public static void main(String[] args) {
        JNative add = new JNative("exportdll.dll", "Add");
        // 设置函数返回值为int
        add.setRetVal(Type.INT);
        // add函数的第一个参数是3
        add.setParameter(0, 3);
        // add函数的第二个参数是4
        add.setParameter(1, 4);  
        // 执行
        add.invoke();
        // 获取结果
        int result = Integer.parseInt(add.getRetVal());  //获取返回结果
        System.out.println(result);
    }
}

3. JNA

性能较低,但是最简单

pom.xml

<dependency>
    <groupId>com.sun.jna</groupId>
    <artifactId>jna</artifactId>
    <version>3.0.9</version>
</dependency>

DllLibrary.java

public interface DllLibrary extends Library{
    int Add(int i, int j);
    float Avg(int i, int j);
}

DllImport.java

public class DllImport {
    public static void main(String[] args) {
        DllLibrary dll = (DllLibrary)Native.loadLibrary("exportdll.dll", DllLibrary.class);
        System.out.println(dll.Add(3, 4));
        System.out.println(dll.Avg(3, 4));
    }
}

由于个人水平有限,文中若有不合理或不正确的地方欢迎指出改正

若文中个人文章链接打不开,请在站内寻找同名文章

文章可能更新不及时,请以个人博客处文章为准

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值