我试图换一个C库(我没写,并且其接口不能更改)使用痛饮。这主要是简单的,但是有一个struct
多数民众赞成给我的麻烦的一个领域。相关struct
定义是这样的:
struct Token {
const char *buffer;
const char *word;
unsigned short wordlen;
// ... other fields ...
};
buffer
是一个普通的C串和通常应(但不可改变)露出。 word
的问题领域。它是一个指向buffer
串内的某处,并旨在被理解为长度wordlen
的字符串。我要揭露这个高层次的语言作为一个正常的只读字符串,因此他们并不总是必须要采取一个切片。
我认为处理这种方式是专门为Token::word
,像这样的“出”类型表:
struct Token {
%typemap (out) const char *word {
$result = SWIG_FromCharPtrAndSize($1, ?wordlen?);
}
}
而这正是我卡住了:我怎么访问父结构的wordlen
领域从这个类型映射?
或者,如果有更好的方法来处理这整个问题,请告诉我有关吧。
不幸的是,它看起来像呷有同时映射多个结构成员的支持。检查所产生的输出,我们得知(arg1)
指向输入结构。因此,我们必须:
word
不变的,所以不产生set
包装。SWIG_FromCharPtrAndSize
片段 - 这不是默认情况下可用。word
你愿意,指SWIG_FromCharPtrAndSize
地图(arg1)->wordlen
。wordlen
,因此,它不是映射(通过%ignore
-ING它,否则无法在struct
痛饮可见提供的话)。下面是一个完整的例子。首先,头:
// main.h
#pragma once
struct Token {
const char *word;
unsigned short wordlen;
};
struct Token *make_token(void);
extern char *word_check;
而SWIG模块 - 请注意,我们使用的标题一字不差,只覆盖struct Token
的定义:
// token_mod.i
%module token_mod
%{#include "main.h"%}
%ignore Token;
%include "main.h"
%rename("%s") Token;
struct Token {
%immutable word;
%typemap (out, fragment="SWIG_FromCharPtrAndSize") const char *word {
$result = SWIG_FromCharPtrAndSize($1, (arg1)->wordlen);
}
const char *word;
%typemap (out) const char *word;
};
使用Python来检查工作的事情演示代码:
// https://github.com/KubaO/stackoverflown/tree/master/questions/swig-pair-53915787
#include <assert.h>
#include <stdlib.h>
#include <Python.h>
#include "main.h"
struct Token *make_token(void) {
struct Token *r = malloc(sizeof(struct Token));
r->word = "1234";
r->wordlen = 2;
return r;
}
char *word_check;
#if PY_VERSION_HEX >= 0x03000000
# define SWIG_init PyInit__token_mod
PyObject*
#else
# define SWIG_init init_token_mod
void
#endif
SWIG_init(void);
int main()
{
PyImport_AppendInittab("_token_mod", SWIG_init);
Py_Initialize();
PyRun_SimpleString(
"import sys\n"
"sys.path.append('.')\n"
"import token_mod\n"
"from token_mod import *\n"
"token = make_token()\n"
"cvar.word_check = token.word\n");
assert(word_check && strcmp(word_check, "12") == 0);
Py_Finalize();
return 0;
}
最后,使演示的CMakeLists.txt
- 可以使用Python 2.7或3.x中使用注意:要切换的Python版本,build目录必须被消灭(或至少在它CMake的缓存必须擦拭)。
cmake_minimum_required(VERSION 3.2)
set(Python_ADDITIONAL_VERSIONS 3.6)
project(swig-pair)
find_package(SWIG 3.0 REQUIRED)
find_package(PythonLibs 3.6 REQUIRED)
include(UseSwig)
SWIG_MODULE_INITIALIZE(${PROJECT_NAME} python)
SWIG_ADD_SOURCE_TO_MODULE(${PROJECT_NAME} swig_generated_sources "token_mod.i")
add_executable(${PROJECT_NAME} "main.c" ${swig_generated_sources})
target_include_directories(${PROJECT_NAME} PRIVATE ${PYTHON_INCLUDE_DIRS} ".")
target_link_libraries(${PROJECT_NAME} PRIVATE ${PYTHON_LIBRARIES})
更高层次的语言不在乎wordlen是字的大小。只有C一样。如果你不能改变你是swiging那么C你要保留原样,并记住,你在该字符的大小更高的语言编写。还痛饮和const不喜欢对方。 Hereis那里consts文档