java/android 使用swig编译c/c++ 代码类型转换

今天被同时问到java/android  使用swig编译c/c++ 代码类型转换。想起找个中文版swig看一下,虽然找到了,但也是基本是英文。

中文版首页的:http://www.swig.org/translations/chinese/index.html

中文版swig3.0文档:http://www.swig.org/Doc3.0/SWIGDocumentation.html#CONTENTS

我主要看了java方面的类型跟c/c++ 代码类型转换。

现在用几张图总结一下:

1、默认的原始类型映射

下表列出了默认从Java类型映射到C / c++。


注意,swig包装C char类型作为一个角色。这种类型的指针和数组作为字符串包裹。签署char类型可以使用,如果你想把字符作为有符号数,而不是一个字符。还要注意,所有常量引用原始类型被视为如果他们通过价值。

int和C段的映射适用于32位应用程序用于32位jvm。没有完美的Java和C之间的映射为Java不支持所有的无符号C数据类型。然而,映射允许每个C的值从Java类型。
前一节中介绍了原始类型映射。类和结构体等非基本类型映射使用指针在C / c++端和存储到一个Java长变量的指针被代理类或类型的包装器类。这是否适用于编组为指针类型,通过引用或值。它还适用于任何未知的/不完整的类型,使用类型的包装器类。
总之,C / c++非基本指针类型转换为64位Java长类型,因此jlong JNI类型。Java类型是包装类代理类或类型。
如果您使用的是64位JVM您可能必须覆盖C长,但是可能不是C int默认映射。映射将依赖于系统,例如长需要重新映射在Unix LP64系统(64位长,指针,int 32位),但不是在微软64位Windows将使用P64 IL32(64位指针,int,长32位)模型。这可能是自动化在未来版本的痛饮。注意,Java一次编写到处运行理念适用于所有纯Java代码时,过渡到64位JVM。不幸的是它不会当然适用于JNI代码。

2、Typemaps C / c++类型映射到Java类型

Java模块主要包括中列出的常见typemaps typemaps部分。有许多额外的typemaps为使用SWIG与Java是必要的。其中最重要的实现C / c++类型映射到Java类型:


注意,“在”typemap执法官JNI类型“JNI”typemap举行真正的C / c++类型相反的方向,”“typemap警察真正的C / c++类型JNI类型在“JNI”typemap举行。非基本类型的“在”和“出”typemaps负责铸件之间的C / c++和64位jlong类型指针。没有便携的方法把一个指针变成一个64位整数类型和方法swig主要是可移植的,但休息C / c++混叠的规则。总之,这些规则声明一个指向任何类型绝不能由一个指针引用其他任何不兼容的类型。下面的代码片段可能会帮助更好地理解混淆的规则:

short a;
    short* pa = 0;
    int i = 0x1234;

    a = (short)i;    /* okay */
    a = *(short*)&i; /* breaks aliasing rules */
 %typemap(in) struct Foo * %{
      $1 = *(struct Foo **)&$input; /* cast jlong into C ptr */
    %}
    %typemap(out) struct Bar * %{
      *(struct Bar **)&$result = $1; /* cast C ptr into jlong */
    %} 
    struct Bar {...};
    struct Foo {...};
    struct Bar * FooBar(struct Foo *f);

导致下面的代码,打破了混叠规则:

SWIGEXPORT jlong JNICALL Java_exampleJNI_FooBar(JNIEnv *jenv, jclass jcls,
                                                jlong jarg1, jobject jarg1_) {
  jlong jresult = 0 ;
  struct Foo *arg1 = (struct Foo *) 0 ;
  struct Bar *result = 0 ;
  
  (void)jenv;
  (void)jcls;
  (void)jarg1_;
  arg1 = *(struct Foo **)&jarg1; 
  result = (struct Bar *)FooBar(arg1);
  *(struct Bar **)&jresult = result; 
  return jresult;
}

3、默认的原始类型映射

下表列出了从C / c++默认类型映射。这个表格会告诉你为一个函数类型去期待它使用一个给定的C / c++类型。

注意,swig包装C char类型作为一个角色。这种类型的指针和数组作为字符串包裹。签署char类型可以使用,如果你想把字符作为有符号数,而不是一个字符。还要注意,所有常量引用原始类型被视为如果他们通过价值。
这些类型映射定义的“gotype typemap”。你可能改变typemap,或添加新值,控制C / c++类型是如何映射到类型。

由于输出参数的处理方式的局限性在swig,一个函数与输出参数将不会有多个返回值。相反,您必须通过一个指针到c++函数来告诉它在哪里存储输出值。在去,你供应一片地方的输出参数。

例如,假设您想将modf C数学库中()函数将x分为整体和部分部件(并返回整数部分的参数):

double modf(double x, double *ip);
您可以使用%申请指令:
%include <typemaps.i>
%apply double *OUTPUT { double *ip };
double modf(double x, double *ip);
%include <typemaps.i>
%apply signed char *OUTPUT {char *output};
void f(char *output);

4、包装C数组与Java数组

swig可以阵列封装在一个更自然比默认使用arrays_java Java的方式。我库文件。让我们考虑一个例子:

%include "arrays_java.i";
int array[4];
void populate(int x[]) {
    int i;
    for (i=0; i<4; i++)
        x[i] = 100 + i;
}
这些一维数组可以用作如果他们Java数组:

int[] array = new int[4];
example.populate(array);

System.out.print("array: ");
for (int i=0; i<array.length; i++)
    System.out.print(array[i] + " ");
example.setArray(array);
int[] global_array = example.getArray();

System.out.print("\nglobal_array: ");
for (int i=0; i<array.length; i++)
    System.out.print(global_array[i] + " ");
java数组总是以引用的方式传递,因此一个函数对数组的任何更改将被调用的函数。这里是输出后运行这段代码:

array: 100 101 102 103
global_array: 100 101 102 103

5、STL / c++库

图书馆模块在本节中提供的部分标准c++库包括STL。swig对STL是一项持续的努力的支持。支持非常全面的一些语言模块,但使用的一些较小的模块没有那么多库编写的代码。
下面的表显示了支持c++类和等效痛饮c++库接口库文件。


%module example
%include "std_string.i"

%apply const std::string& {std::string* foo};

struct my_struct
{
  std::string foo;
};

说了那么多,文档看了那么多,都是类型的转换。

还有一个很重要的特点就是。返回值时候可以以多参数的形式返回。

		double[] dSource1 = new double[1];
		double[] dSource2 = new double[1];
		double[] dSource3 = new double[1];
		double[] deditViewInputData = new double[3];
		SourceCoord.XYZ_2(deditViewInputData[0],deditViewInputData[1], deditViewInputData[2],
					dSource1, dSource2, dSource3);
上面是java代码,那么计算出来的值是放在三个double数组里面。

最后附上一个标准c++头文件

#ifndef _2013_H_
#define _2013_H_
#include <string>
#include <stdio.h>
#include <stdlib.h>
#ifdef SWIG
%include "std_string.i"
%include "typemaps.i"
%include "arrays_java.i"
%apply signed char[] {char*}
#endif // SWIG
class 2013
{
public:
    2013(void);
    ~2013(void);
public:
    int  Auth(const std::string& m_N, const std::string& m_ID, const std::string& m_CODE, char *m_DATA);
    int  NetAuth(const std::string& m_JSH,const std::string& m_KEY,const std::string& m_PID,const std::string& m_Code,char *Return_Mes);
    void EncodeBase64(const std::string& Src,int Src_len,char *base64code);
private:
    void EncodeBase64(char *Src,int Src_len,char *base64code);
    void DecodeBase64(const char *szCoded, char *Des,int &Des_len);
    int  CheckkCRC16( unsigned  char *data, int Len);
};
#endif


我之前写android eclipse 部署编译swig以及一些知识博客

 Android ndk开发swig编译jni接口  http://blog.csdn.net/qq_16064871/article/details/44658379

 Android ndk开发swig编译jni接口配置文件(二) http://blog.csdn.net/qq_16064871/article/details/45110909

参考资料

http://blog.csdn.net/liminlu0314/article/details/6945452

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值