通过Swig封装JAVA Native Interface调用C++动态库

运行环境

Windows10 专业版 64位

JDK 1.8.0.121 64位

Eclipse Jee Neon

Visual Studio 2015 专业版

Swigwin3.0.12

先从Swig官网下载下最新版 Swig windows版,解压到任意目录.

我是解压在 D:\sdk\swigwin-3.0.12

设置环境变量 SWIG_HOME = D:\sdk\swigwin-3.0.12

PATH里多加个 %SWIG_HOME%

使我们在任意目录都能方便使用swig.exe

JAVA 程序为 webapp,与控制台程序略有不同,网上例子大多为控制台程序调用C++动态库.使我一开始走了很多弯路.控制台的例子网上很多这里就不写了.

先上CPP代码:

在VS2015里创建控制台空项目,之所以要空项目,是省得到VS自动给你生成没用的 main函数,到时要删很烦.

在项目里新增类 SwigDemoToJava

SwigDemoToJava.h

/*SwigDemoToJava.h*/
#pragma once

class SwigDemoToJava
{
public:
	int SwigAdd(int i, int j);

};

SwigDemoToJava.cpp

#include "SwigDemoToJava.h"

int SwigDemoToJava::SwigAdd(int i, int j)
{
	return i + j;
}

很简单的一个类,测试用就实现一个整数加法.

然后在项目里新增Swig接口文件

SwigDemo.i

%module SwigDemo
%{
#include "SwigDemoToJava.h"
%}

%include "SwigDemoToJava.h"

这里解释一下,%module ,模块名 ,不能和C++类名相同,

Win+R运行 cmd.exe打开命令窗口

进入到 C++项目所在源代码目录,(此时swigdemo.i也应在此)

运行:  Swig -c++ -java -package com.myjavaproject.library -ourdir "e:\javaspace\myjavaproject\src\main\java\com\myjavaproject\library" swigdemo.i

当然,你也可以不指定 -outdir,

如果不指定-outdir,会在当前目录下生成4个文件 1个SwigDemo_wrap.cxx 和三个.java文件,手动把三个java文件copy到你的java项目中去.

在VS里把swigDemo_wrap.cxx加入到工程,然后重新编译,生成swigdemo.dll

把生成的dll复制到  java.library.path里列出来的任意目录..这里有点区别,在控制台java程序中java.library.path中列出的任意目录都可以放dll,JAVA程序都能调用到dll

但是如果是webApp,把DLL放在有些目录就不能调用.比如我之前把dll放在C:\Program Files\Java\jre1.8.0_121\bin\server 下(该目录也是 library.path)

控制台程序可以正常调用DLL,而webApp则能loadlibrary,但一new对像就异常.

我个人猜测,可能是控制台APP直接创建新JVM线程,而webApp依靠于Tomcat的原因,具体什么原因不明,以后有空再研究了.

转回正题.编写JAVA程序.

我原来有个JAVA项目,项目名我这里暂时用myjavaproject代替.

为了简单,我直接在控制器里调用C++动态库了,

直接代码:

package com.myjavaproject.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.myjavaproject.controller.BaseController;
import com.myjavaproject.library.SwigDemoToJava;;

@Controller
@RequestMapping("/NativeDemo")
public class NativeDemoController extends BaseController {

	@RequestMapping("/demo1.do")
	@ResponseBody
	public String demo1(String param1,String param2) {
		try {
			System.loadLibrary("SwigDemo");
			SwigDemoToJava sd1 = new SwigDemoToJava();
			return "SwigDemo is:"
			+String.valueOf(sd1.SwigAdd(Integer.parseInt(param1),Integer.parseInt(param2)));
		} catch (Exception e) {
			return e.getMessage();
		}
	}
}

保存,运行

在浏览器里输入http://localhost:8080/myjavaproject/NativeDemo/demo1.do?param1=11¶m2=22

返回:

SwigDemo is:33

成功调用C++动态库里的SwigAdd成员函数.

注意事项:

1.Swig接口文件里%module 模块名,不能同C++类名一样

2.在WebApp里,不是所有的library path都能放动态库.我最后是把DLL直接放在C:\Windows\System32 下面,下次有空再研究一下怎么放在WebApp指定目录....

3.在swig命令里最好指定package.并放到项目的相应目录下.

4.还没想到....

最后留下此笔记,以备未来哪天忘记了方便查阅


你可能感兴趣的:(JAVA,C++,SWIG)