【IntelliJ IDEA 2019.2】vs2008编写C++ dll,被java调用

1.新建一个工程。

2.关键点,改成生成dll.

关键点2:

带MTd中的T表示静态链接,这是易错点之一,错误的提示信息为:应用程序无法启动,因为应用程序的并行配置不正确

最后,为了方便调试,设置自动把dll文件复制到目标目录:

copy /y x64\Debug\SerialPort_dll.dll ..\SerialPort.dll

或者

copy /y x64\Debug\xxx.dll ..\out\production\xxxxxx\xxx.dll

3.输入代码。

#include <Windows.h>
extern "C" _declspec(dllexport) char* go(char *ch)
{ 
    //MessageBox(NULL, TEXT(ch), TEXT("你好"), MB_OK);
    return "来自dll的问候";
}

易错点:string 是不能作为返回值

虽然前面加了 extern "C" 所以,但用的是C的语法,是C++的语法,那么,string 是不能作为返回值,但可以作为传入的参数的原因是什么呢?是因为dll和exe主程序,实际上是两个不同的进程了,不同进程间的内存是不共享的,所以,当使用string作为返回值时,就会出错了,因为string申请空间是在dll,释放却在exe里,exe就会出错,因为根本就没有申请这块内存,哪来的内存去释放呢?明白了这一点,就好办了。

如果想实现 string func(),

则可以写成 char* func(), 或者 void func(string &ret) , (建议第2种写法)。

 

常见错误:

Exception in thread "main" java.lang.Error: Invalid memory access

通常是因为dll函数接口参数类型错误:

1.不能使用string类型。

 

4.先用C++测试调用一下。

以下这段代码参考自:https://www.cnblogs.com/Joetao/articles/10216993.html

#include <iostream>
#include <windows.h>

HINSTANCE hDll = LoadLibrary("vs2008_dll_test.dll");
typedef char* (*pType_go)(char *ch);
pType_go go = (pType_go)GetProcAddress(hDll, "go");

void main()
{
	char *ret = go("hello,dll");
	printf(ret);
	FreeLibrary(hDll);
	while (1){}
}

如果要分成头文件和CPP两个文件,则可以这要写:

头文件:

#pragma once
#include <iostream>
#include <windows.h>

typedef char* (*pType_Get_dll_version)(void);

extern HINSTANCE hDll;
extern pType_Get_dll_version Get_dll_version;

CPP文件:

#include "SerialPort_dll.h"

HINSTANCE hDll = LoadLibrary("SerialPort.dll");
pType_Get_dll_version Get_dll_version = (pType_Get_dll_version)GetProcAddress(hDll, "Get_dll_version");

5.java调用

参考自: https://www.cnblogs.com/AngeLeyes/p/9449390.html

1.下载JNA包

JNA的Github(这就是JNA开源项目的官网了): https://github.com/java-native-access/jna

下载jar包,如下图:

2.把jar包放到工程目录下,新建一个lib文件夹,然后把jar包放里面。

3.点击"add as library",把该库加入到工程里编译。

4.复制生成的dll到java项目的根目录,即 out/production/*/ ,如下 :

然后写调用代码(JNA方式)

说明: “JNAUtilsTest.Dll INSTANCE” 里的“JNAUtilsTest”就是当前类的名称。

import com.sun.jna.Library;
import com.sun.jna.Native;

public class JNAUtilsTest {
    public interface Dll extends Library {
        JNAUtilsTest.Dll INSTANCE = (JNAUtilsTest.Dll) Native.load("vs2008_dll_test", JNAUtilsTest.Dll.class);// 加载动态库文件
        String go(String s);
    }

    public static void main(String[] args){
        System.setProperty("jna.encoding", "GBK");//解决中文乱码
        String go = Dll.INSTANCE.go("777");
        System.out.println(go);
    }
}

C++接口传递的变量怎么和JAVA对接起来呢?这是一个问题,可参考下面的链接。

C++标准库与Java基础类对照

 

运行出现问题1:

Exception in thread "main" java.lang.UnsatisfiedLinkError: %1 不是有效的 Win32 应用程序。

解决方法:

因为jre是64位的,而dll是32位的,所以就出现了这个问题,所以解决方法是把dll改成64位的,那么,怎么用vs2008生成64位dll呢?

运行出现问题2:

应用程序无法启动,因为应用程序的并行配置不正确

解决方法:是因为使用MFC功能,而找不到相关的MFC系统库,最简单的方法是把MFC相关的代码删除就行,所以,代码变成了,

#include <Windows.h>
_declspec(dllexport) char* go(char *ch)
{ 
	//MessageBox(NULL, TEXT(ch), TEXT("你好"), MB_OK);
	return "来自dll的问候";
}

运行出现问题3:

Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'go': 找不到指定的程序。

解决方法:加上“extern "C" ”,如下,

最后终于运行成功,运行结果如下:

 

附件1 vs2008生成64位dll

参考自: https://blog.csdn.net/clever101/article/details/8844314

1.重新打开vs2008安装文件,再安装多一个“X64编译器和工具”,如下图:

2.安装完后,就多了一个

3.打开一个工程,点击“配置管理器”

4.

5.

6.关闭后就多了一个“X64”的选项。不过,注意,生成的文件的文件夹也变了,如下:

 

小技巧

可以再加多一步,使生成的dll文件自动复制到目标位置,如下:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值