目录

  • 相关教程
  • 环境配置
  • 0基础上手例子(C/C++)
  • 使用CMake的例子(C语言)
  • 使用CMake的例子(C++)

本文主要是手把手教萌新们如何用官方用例构建(有许多本人亲身踩坑血泪史)

相关教程

  • Swig超详细入门教程(Java调用C/C++, CMake)——更新于2021.12
  • 【超详细教程】Java调用C/C++中的Debug(JNI/Swig通用)——更新于2022.01
  • Swig超详细入门教程(Python3调用C/C++, CMake)——更新于2021.12
  • 【从零开始】C++调用python(CMake,Clion,windows,包含一些常见错误)

环境配置

  1. swig官网教程:http://www.swig.org/tutorial.html
    swigwin下载地址:https://sourceforge.net/projects/swig/files/swigwin/

    安装后为了方便,可以添加安装目录到环境变量path。
SWIG_DIR = C:\swigwin-4.0.2
SWIG_EXECUTABLE = C:\swigwin-4.0.2\swig.exe
  1. C++:我使用的是Mingw-w64(GCC 9.3.0),如果使用高版本的python,gcc版本不能太低,否则会报错。记得配置环境变量哦! 超详细教程:windows安装MSYS2(mingw && gcc)——更新于2021.11
$ gcc --version
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  1. Clion:正常安装配置好Toolchains就可以了。(当然也可以选用其他IDE)
  2. IDEA:正常安装后,在菜单栏依次 File->Project Structure->Project->Project SDK->ADD SDK->Download SDK,环境变量JAVA_HOME = C:\.jdks\openjdk-17.0.1

0基础上手例子(C/C++)

首先我们看一个最简单的例子,如何用swig让java调用c。这里使用的是mingw和java8。

首先构建如下example.c文件

/* File : example.c */#include <time.h>double My_variable = 3.0;int fact(int n) {if (n <= 1) return 1;else return n * fact(n - 1);
}int my_mod(int x, int y) {return (x % y);
}char *get_time() {time_t ltime;time(&ltime);return ctime(&ltime);
}

之后构建example.i文件

 /* example.i */%module example%{/* Put header files here or function declarations like below */extern double My_variable;extern int fact(int n);extern int my_mod(int x, int y);extern char *get_time();%}extern double My_variable;extern int fact(int n);extern int my_mod(int x, int y);extern char *get_time();

在当前目录打开cmd,然后输入:

$ swig -java example.i
$ gcc -c example.c example_wrap.c -I "C:\Program Files\jdk1.8.0_262\include" -I "C:\Program Files\jdk1.8.0_262\include\win32"
$ gcc -shared example.o  example_wrap.o -mno-clwb -Wl,--add-stdcall-alias  -o example.dll

如果想用C++编译可以用如下(注意和上面的区别):

$ swig -c++ -java example.i
$ g++ -c example.c example_wrap.cxx -I "C:\Program Files\jdk1.8.0_262\include" -I "C:\Program Files\jdk1.8.0_262\include\win32"
$ g++ -shared example.o  example_wrap.o -mno-clwb -Wl,--add-stdcall-alias  -o example.dll

创建main.java

/* main.java */
public class main {public static void main(String argv[]) {System.loadLibrary("example");System.out.println(example.getMy_variable());System.out.println(example.fact(5));System.out.println(example.get_time());}
}
 $ javac main.java$ java main3.0120Mon Mar  4 18:20:31  2002$

使用CMake的例子(C语言)

项目工程目录结构:

和之前一样,我们首先构建如下example.c文件

/* File : example.c *//* A global variable */
double Foo = 3.0;/* Compute the greatest common divisor of positive integers */
int gcd(int x, int y) {int g;g = y;while (x > 0) {g = x;x = y % x;y = g;}return g;
}

之后构建example.i文件

/* File : example.i */
%module example%inline %{extern int    gcd(int x, int y);
extern double Foo;
%}

我们创建CMakeLists.txt:

#[[ CMakeLists.txt ]]#指定CMake的最小版本
cmake_minimum_required(VERSION 3.17)
project(Example)set(CMAKE_CXX_STANDARD 20)include_directories($ENV{JAVA_HOME}/include)
include_directories($ENV{JAVA_HOME}/include/win32)#指定你的.cxx等文件的目录
include_directories(${PROJECT_SOURCE_DIR}/src)#寻找安装好的swig,其实就是去电脑中找你安装好的Swig环境,所以我们需要提前安装环境。
find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})
#JAVA文件输出目录 -outdir
set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/java)
#指定一个输出目录名,用于放置生成的源文件。例如输出的exampleJAVA_wrap.cxx文件等的位置
set(SWIG_OUTFILE_DIR ${CMAKE_CURRENT_BINARY_DIR}/cpp)
#开始生成
swig_add_library(example LANGUAGE java SOURCES src/example.i src/example.c)

之后我们重载CMake项目

然后点击build:

之后会生成:

把这几个文件复制到一个新建的文件夹里,然后再新建runme.java:

/* File : runme.java */public class runme {static {try {System.loadLibrary("example");} catch (UnsatisfiedLinkError e) {System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);System.exit(1);}}public static void main(String argv[]) {// Call our gcd() functionint x = 42;int y = 105;int g = example.gcd(x, y);System.out.println("The gcd of " + x + " and " + y + " is " + g);// Manipulate the Foo global variable// Output its current valueSystem.out.println("Foo = " + example.getFoo());// Change its valueexample.setFoo(3.1415926);// See if the change took effectSystem.out.println("Foo = " + example.getFoo());}
}

运行runme.main():

The gcd of 42 and 105 is 21
Foo = 3.0
Foo = 3.1415926

使用CMake的例子(C++)

项目工程目录结构:

和之前一样,我们首先构建如下example.cxx文件

/* File : example.cxx */#include "example.h"

之后构建example.i文件

/* File : example.i */
%module(directors="1") example
%{#include "example.h"
%}%include "std_vector.i"
%include "std_string.i"/* turn on director wrapping for Manager */
%feature("director") Employee;
%feature("director") Manager;%include "example.h"

之后构建example.h文件

/* File : example.h */#include <cstdio>
#include <iostream>
#include <vector>
#include <string>
#include <cmath>class Employee {private:std::string name;
public:Employee(const char* n): name(n) {}virtual std::string getTitle() { return getPosition() + " " + getName(); }virtual std::string getName() { return name; }virtual std::string getPosition() const { return "Employee"; }virtual ~Employee() { printf("~Employee() @ %p\n", (void *)this); }
};class Manager: public Employee {public:Manager(const char* n): Employee(n) {}virtual std::string getPosition() const { return "Manager"; }
};class EmployeeList {std::vector<Employee*> list;
public:EmployeeList() {list.push_back(new Employee("Bob"));list.push_back(new Employee("Jane"));list.push_back(new Manager("Ted"));}void addEmployee(Employee *p) {list.push_back(p);std::cout << "New employee added.   Current employees are:" << std::endl;std::vector<Employee*>::iterator i;for (i=list.begin(); i!=list.end(); i++) {std::cout << "  " << (*i)->getTitle() << std::endl;}}const Employee *get_item(int i) {return list[i];}~EmployeeList() { std::vector<Employee*>::iterator i;std::cout << "~EmployeeList, deleting " << list.size() << " employees." << std::endl;for (i=list.begin(); i!=list.end(); i++) {delete *i;}std::cout << "~EmployeeList empty." << std::endl;}
};

我们创建CMakeLists.txt(注意这里和C语言的CMakeLists.txt的区别):

#[[ CMakeLists.txt ]]#指定CMake的最小版本
cmake_minimum_required(VERSION 3.17)
project(Example)set(CMAKE_CXX_STANDARD 20)include_directories($ENV{JAVA_HOME}/include)
include_directories($ENV{JAVA_HOME}/include/win32)#指定你的.cxx等文件的目录
include_directories(${PROJECT_SOURCE_DIR}/src)#寻找安装好的swig,其实就是去电脑中找你安装好的Swig环境,所以我们需要提前安装环境。
find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})
#JAVA文件输出目录 -outdir
set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/java)
#指定一个输出目录名,用于放置生成的源文件。例如输出的exampleJAVA_wrap.cxx文件等的位置
set(SWIG_OUTFILE_DIR ${CMAKE_CURRENT_BINARY_DIR}/cpp)
#c ++模式
set_property(SOURCE src/example.i PROPERTY CPLUSPLUS ON)
#开始生成
swig_add_library(example LANGUAGE java SOURCES src/example.i)

之后我们重载CMake项目

然后点击build:

之后会生成:

把这几个文件复制到一个新建的文件夹里,然后再新建runme.java:

/* File : runme.java */// This file illustrates the cross language polymorphism using directors.
// CEO class, which overrides Employee::getPosition().class CEO extends Manager {public CEO(String name) {super(name);}public String getPosition() {return "CEO";}// Public method to stop the SWIG proxy base class from thinking it owns the underlying C++ memory.public void disownMemory() {swigCMemOwn = false;}
}public class runme {static {try {System.loadLibrary("example");} catch (UnsatisfiedLinkError e) {System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);System.exit(1);}}public static void main(String argv[]) {// Create an instance of CEO, a class derived from the Java proxy of the // underlying C++ class. The calls to getName() and getPosition() are standard,// the call to getTitle() uses the director wrappers to call CEO.getPosition().CEO e = new CEO("Alice");System.out.println(e.getName() + " is a " + e.getPosition());System.out.println("Just call her \"" + e.getTitle() + "\"");System.out.println("----------------------");// Create a new EmployeeList instance.  This class does not have a C++// director wrapper, but can be used freely with other classes that do.EmployeeList list = new EmployeeList();// EmployeeList owns its items, so we must surrender ownership of objects we add.e.disownMemory();list.addEmployee(e);System.out.println("----------------------");// Now we access the first four items in list (three are C++ objects that// EmployeeList's constructor adds, the last is our CEO). The virtual// methods of all these instances are treated the same. For items 0, 1, and// 2, all methods resolve in C++. For item 3, our CEO, getTitle calls// getPosition which resolves in Java. The call to getPosition is// slightly different, however, because of the overridden getPosition() call, since// now the object reference has been "laundered" by passing through// EmployeeList as an Employee*. Previously, Java resolved the call// immediately in CEO, but now Java thinks the object is an instance of// class Employee. So the call passes through the// Employee proxy class and on to the C wrappers and C++ director,// eventually ending up back at the Java CEO implementation of getPosition().// The call to getTitle() for item 3 runs the C++ Employee::getTitle()// method, which in turn calls getPosition(). This virtual method call// passes down through the C++ director class to the Java implementation// in CEO. All this routing takes place transparently.System.out.println("(position, title) for items 0-3:");System.out.println("  " + list.get_item(0).getPosition() + ", \"" + list.get_item(0).getTitle() + "\"");System.out.println("  " + list.get_item(1).getPosition() + ", \"" + list.get_item(1).getTitle() + "\"");System.out.println("  " + list.get_item(2).getPosition() + ", \"" + list.get_item(2).getTitle() + "\"");System.out.println("  " + list.get_item(3).getPosition() + ", \"" + list.get_item(3).getTitle() + "\"");System.out.println("----------------------");// Time to delete the EmployeeList, which will delete all the Employee*// items it contains. The last item is our CEO, which gets destroyed as well.list.delete();System.out.println("----------------------");// All done.System.out.println("java exit");}
}

运行runme.main():

Alice is a CEO
Just call her "CEO Alice"
----------------------
New employee added.   Current employees are:Employee BobEmployee JaneManager TedCEO Alice
----------------------
(position, title) for items 0-3:Employee, "Employee Bob"Employee, "Employee Jane"Manager, "Manager Ted"CEO, "CEO Alice"
----------------------
~EmployeeList, deleting 4 employees.
~Employee() @ 00000299491925A0
~Employee() @ 0000029949192970
~Employee() @ 00000299491929C0
~Employee() @ 00000299491928F0
~EmployeeList empty.
----------------------
java exitProcess finished with exit code 0

Swig超详细入门教程(Java调用C/C++, CMake)——更新于2021.12相关推荐

  1. TypeScript超详细入门教程(上)

    TypeScript超详细入门教程(上) 01 开篇词:Hello~TypeScript 01 开篇词:Hello~TypeScript 更新时间:2019-10-30 13:49:46 既然我已经踏 ...

  2. Apollo Control——超详细入门教程(二):连续状态空间方程离散化与离散LQR公式推导

    专栏文章列表 Apollo Control--超详细入门教程(一):基于道路误差的车辆动力学模型 Apollo Control--超详细入门教程(二):连续状态空间方程离散化与离散LQR公式推导 Ap ...

  3. 消息队列之延迟队列超详细入门教程速看

    一. 延迟队列的应用场景 1.具体应用 关于消息队列我们已经很熟悉了,我们知道在消息队列中可以实现延迟队列效果,那你知道延迟队列有哪些使用场景吗?这里我给大家总结了延迟队列的几个经典使用场景,看看你的 ...

  4. Nginx超详细入门教程

    1 Nginx入门教程 Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like协议下发行.由俄罗斯的程序设计师IgorSysoev所开 ...

  5. Redis基础、超详细入门教程

    最近学习了某站上老师讲的Redis入门课程,老师讲的很基础,从最初的Redis安装到搭建集群,到最后的问题讲解.适合刚刚接触Redis和想要复习Redis的初学者,在这里和老师的笔记做了个同步文档,希 ...

  6. 【建议收藏】Redis超详细入门教程大杂烩

    写在前边 Redis入门的整合篇.本篇也算是把2021年redis留下来的坑填上去,重新整合了一翻,点击这里,回顾我的2020与2021~一名大二后台练习生 NoSQL NoSQL(NoSQL = N ...

  7. React 超详细入门教程

    文章目录 一,React简介 1.什么是React 2.React工作原理 3.React历史 4.React的特点 5. React 高效的原因 6.React 官方网站 二,React基本使用 1 ...

  8. python入门教程(非常详细)-Python超详细入门教程(上)

    课程简介 2019千锋全新打造Python教程,深入浅出的讲解Python语言的基础语法,注重基本编程能力训练,深入解析面向对象思想,数据类型和变量.运算符.流程控制.函数.面向对象.模块和包.生成器 ...

  9. python 知识点视频,Python超详细入门教程-Python基础视频教程-千锋教育视频资源库...

    第1节 - python简介 点击播放 第2节 - python特点 点击播放 第3节 - 安装与配置 点击播放 第4节 - pip包管理命令 点击播放 第5节 - 安装问题总结 点击播放 第6节 - ...

最新文章

  1. python一切皆对象的理解_Python中万物皆对象?的理解
  2. Leet Code OJ 20. Valid Parentheses [Difficulty: Easy]
  3. 搜索引擎提交注意事项
  4. atom编写python程序_编写我们的第一个Python程序,print.py
  5. python 比较运算符放在列表中_在Python3中将运算符放在列表中
  6. 赚大钱必备 怎样成为赚钱高手(图)
  7. Vbs压缩备份文件夹以日期命名
  8. linux中mysql不显示中文_linux中解决mysql中文乱码方法
  9. mysql之高性能索引
  10. 171.Excel表列序号
  11. 机器学习实战之路—— 1 线性回归 (二)
  12. LocalDate获取时间戳
  13. w ndows7打印机添加,Windows7操作系统下添加打印机教程
  14. 惠普HP Deskjet Ink Advantage 3540 打印机驱动
  15. Type error: Too few arguments to function Illuminate\Support\Manager::createDriver()
  16. 利用kmplayer查看wav声音文件的采样率
  17. Navicat连接mysql报错is not allowed to connect to this MySQL
  18. 华为AR路由器策略模板建立ipsec过程
  19. java抽象工厂模式_JAVA设计模式-抽象工厂模式
  20. ​戴尔科技集团+微软Azure Stack HCI:引领混合云上云新范式

热门文章

  1. 驾驶员蓝牙耳机怎么选?开车可以打电话的蓝牙耳机
  2. 雅思经验(15)之让AI帮你改雅思作文
  3. python大作业五子棋人人对战_简单的五子棋(人人对战)
  4. 为什么朋友圈总有些环游世界的人? 可能大部分是...
  5. 前端面试每日3+1(周汇总2019.06.16)
  6. 这是一个大学混子靠着努力收获大厂offer的故事,也是我大学四年的一个回顾(下)
  7. ThinkPHP5篮球培训报名系统
  8. 一桩婚姻引发的数学建模
  9. lol-登陆英雄联盟出错
  10. 湖北民族学院2015CSDN俱乐部招新