gpt4 book ai didi

c - SWIG:结构字段的 "out"类型映射需要访问相同结构的另一个字段

转载 作者:太空狗 更新时间:2023-10-29 17:26:28 26 4
gpt4 key购买 nike

我正在尝试使用 SWIG 包装一个 C 库(我没有编写,并且其接口(interface)无法更改)。大部分都很简单,但是一个 struct 的一个字段给我带来了麻烦。相关的 struct 定义如下所示:

struct Token {
const char *buffer;
const char *word;
unsigned short wordlen;
// ... other fields ...
};

buffer 是一个普通的 C 字符串,应该正常公开(但不可变)。 word 是问题字段。它是指向 buffer 字符串中 某处的指针,应被理解为长度为 wordlen 的字符串。我想将它作为普通的只读字符串公开给高级语言,这样它们就不必总是分片了。

认为处理这个问题的方法是使用专门用于Token::word 的“out”类型映射,如下所示:

struct Token {
%typemap (out) const char *word {
$result = SWIG_FromCharPtrAndSize($1, ?wordlen?);
}
}

这就是我陷入困境的地方:如何从该类型映射访问父结构的 wordlen 字段?

或者如果有更好的方法来处理整个问题,请告诉我。

最佳答案

不幸的是,SWIG 似乎不支持同时映射多个结构成员。检查生成的输出,我们了解到 (arg1) 指向输入结构。因此,我们必须:

  1. 使 word 不可变,这样就不会生成 set 包装器。
  2. 导入 SWIG_FromCharPtrAndSize 片段 - 默认情况下不可用。
  3. 根据需要使用 SWIG_FromCharPtrAndSize 映射 word,引用 (arg1)->wordlen
  4. 跳过 wordlen,这样它就不会被映射(通过 %ignore 对其进行映射,或者不在可见的 struct 中提供它痛饮)。

下面是一个完整的例子。一、标题:

// main.h
#pragma once

struct Token {
const char *word;
unsigned short wordlen;
};

struct Token *make_token(void);
extern char *word_check;

还有 SWIG 模块 - 请注意,我们逐字使用 header ,仅覆盖 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 版本,必须删除构建目录(或者至少必须删除其中的 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})

关于c - SWIG:结构字段的 "out"类型映射需要访问相同结构的另一个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53915787/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com