swig

swig

Posted by nomadli on March 30, 2018

介绍

Simplified Wrapper and Interface Generator (SWIG) ,基本思想就是向脚本语言接口公开 C/C++ 代码。SWIG 允许您向广泛的脚本语言公开 C/C++ 代码,包括Perl、PHP、Python、Tcl、Ruby、C#、CLISP、Allegro CL、CFFI、UFFI、Java、Modula-3、OCAML、R、Guile、MzScheme、Chicken

python

  1. %module 后跟将C接口封装成python模块的名称
  2. %{ … %} 包含C的宏和类型、函数声明 或直接 #include 头文件
  3. 声明要封装的函数、变量、类型 也可以直接%include 头文件
  4. 执行swig -python -c xxx.i
  5. python setup.py build 生成python包

    EncryptTool.h   
    int encrypt(const char *in, const char *out);
    int decrypt(const char *in, const char *out);
    
    EncryptTool.cpp
    int encrypt(const char *in, const char *out){
        ... 
    }
    int eecrypt(const char *in, const char *out){
        ...
    }
        
    EncryptTool.i
    %module EncryptTool
    %{
        #define SWIG_FILE_WITH_INIT
        #include "EncryptTool.h"
    %}
    %include "EncryptTool.h" 或者
    int Encrypt(const char *in, const char *out);
    int Decrypt(const char *in, const char *out);
        
    swig -python -c++ EncryptTool.i
        
    setup.py
    #!/usr/bin/python2.7
    from distutils.core import setup, Extension
    #生成一个扩展模块
    pymodule = Extension('_EncryptTool', #模块名,必须有下划线
                         sources=['EncryptTool_wrap.cxx', #swig 生成
                                  'Encrypt.cpp',
                                  'EncryptTool.cpp',
                                  'xxx...'
                                 ],
                       )
    

setup(name = ‘EncryptTool’, #打包后的名称 version = ‘0.1’, author = ‘SWIG Docs’, description = ‘Simple swig pht from docs’, ext_modules = [pht_module], #与上面的扩展模块名称一致 py_modules = [‘EncryptTool’], #需要打包的模块列表 )

python setup.py build
生成_EncryptTool.so和EncryptTool.py

java

  1. JAVA_INCLUDE=xxx/jdkxx_xx/include
  2. JAVA_BIN=xxx/jdkxx_xx/bin
  3. %module 后跟将C接口封装成java的类名称
  4. %{ … %} 包含C的宏和类型、函数声明直接#include 头文件
  5. 声明要封装的函数、变量、类型 也可以直接%include 头文件
  6. JAVA_INCLUDE=xxx/jdkxx_xx/include JAVA_BIN=xxx/jdkxx_xx/bin swig -java -package com.nomadli.xx -Ixx/c头文件路径 与I直接不能有空格 -outdir ./ xxx/xx.i
  7. 使用gcc、cmake、llvm等生成c动态库

donet

  1. swig -csharp -Ixx/c头文件路径 与I直接不能有空格 -outdir ./ xx/xx.i
    export unsigned long std_call nomadli_export_function(uint8 *data, uintlen) {
    }
    [DllImport("libname32", EntryPoint="nomadli_export_function")]
    private static extern uint any_name_32(byte[] data, uint dlen);
    [DllImport("libname64", EntryPoint="nomadli_export_function")]
    private static extern uint any_name_64(byte[] data, uint dlen);
    /// <summary>
    /// 介绍
    /// </summary>
    /// <param name="data">xxx</param>
    /// <return>xxx</return>
    public static string CSharpFunc(string data) {
        if (IntPtr.Size == 8) {
            any_name_64(data, (uint)data.len);
        } else {
            any_name_32(data, (uint)data.len);
        }
    }
    

nodejs

  1. 头文件
  2. 例子
  3. set(CMAKE_SHARED_LINKER_FLAGS “${CMAKE_SHARED_LINKER_FLAGS} -undefined dynamic_lookup”) mac 忽略符号
  4. 不要test任意test都会导致连接动态库报错 ``` #define NAPI_VERSION (3) //使用的napi的版本 #define NAPI_EXPERIMENTAL (1) //开启扩展 #include <node/node_api.h>

static void finalise(napi_env env, void *finalise_data, void *finalise_hint) { }

napi_value* encrypt_len(napi_env env, napi_callback_info info) { size_t argc = 3; napi_value args[3]; napi_status status = napi_get_cb_info(env, info, &argc, args, NULL, NULL); if (status != napi_ok || argc < 3) { return NULL; }

napi_typedarray_type args_type;
status = napi_typeof(env, args[0], &args_type);
if (status != napi_ok || (args_type != napi_uint8_array && args_type != napi_int8_array)) {
    return NULL;
}

status = napi_typeof(env, args[1], &args_type);
if (status != napi_ok || (args_type != napi_uint8_array && args_type != napi_int8_array)) {
    return NULL;
}

status = napi_typeof(env, args[2], &args_type);
if (status != napi_ok || (args_type != napi_uint8_array && args_type != napi_int8_array)) {
    return NULL;
}

char *key, *iv, *pass, *data;
size_t klen, ilen, plen;
status = napi_get_arraybuffer_info(env, args[0], &key, &klen);
if (status != napi_ok) {
    return NULL;
}

status = napi_get_arraybuffer_info(env, args[1], &iv, &ilen);
if (status != napi_ok) {
    return NULL;
}

status = napi_get_arraybuffer_info(env, args[2], &pass, &plen);
if (status != napi_ok) {
    return NULL;
}

size_t o_len = 0;
if (encrypt(key, klen, iv, ilen, pass, plen, NULL, &o_len) != 0 || o_len <= 0) {
    return NULL;
}

data = (char*)malloc(o_len);
if (data == NULL) {
    return NULL;
}

if (em_db_pass_encrypt(key, klen, iv, ilen, pass, plen, data, &o_len) != 0 || o_len <= 0) {
    return NULL;
}

napi_value ret;
status = napi_create_external_arraybuffer(env, data, o_len, em_node_js_finalise, NULL, &ret);
if (status != napi_ok) {
    return NULL;
}

return ret; }

napi_value em_nod_js_init(napi_env env, napi_value exports) { napi_property_descriptor fun_descriptors[] = { { .utf8name = “encrypt”, .name = NULL, .method = encrypt, .getter = NULL, .setter = NULL, .value = NULL, .attributes = napi_default, .data = NULL }, { .utf8name = “decrypt”, .name = NULL, .method = decrypt, .getter = NULL, .setter = NULL, .value = NULL, .attributes = napi_default, .data = NULL } }; napi_status status = napi_define_properties(env, exports, sizeof(fun_descriptors) / sizeof(fun_descriptors[0]), fun_descriptors); if (status != napi_ok) {

}
return exports; } ```