swig char ** 作为指向 char * 的指针

Posted

技术标签:

【中文标题】swig char ** 作为指向 char * 的指针【英文标题】:swig char ** as a pointer to a char * 【发布时间】:2017-10-20 10:02:26 【问题描述】:

我无法将 swig 和 char ** 作为指向变量 char * 的指针(而不是作为 char * 的列表!!!)。我找不到将指针包装到 char * 的方法。

目的是将连接的结果写入指针所引用的char *中。

以下是我的代码:

文件指针.cpp:

#include "pointers.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

void conc(char *str1, char *str2, char **res)
  char *aux = (char *)malloc(strlen(str1)+strlen(str2)+1);
  strcpy(aux,str1);
  strcat(aux,str2);
  strcpy(*res,aux);
  free(aux);

文件指针.h

void conc(char *str1, char *str2, char **res)

文件指针.i

%module pointers
%
#define SWIG_FILE_WITH_INIT
#include "pointers.h"
%

%include "typemaps.i"
%include "cpointer.i"
%include "cstring.i"

%pointer_functions(char *, charp);
extern void conc(char *str1, char *str2, char **res);

文件 setup.py:

from distutils.core import setup, Extension


pointers_module = Extension('_pointers',
                       sources=['pointers_wrap.cxx', 'pointers.cpp'],
                       )

setup (name = 'pointers',
   version = '0.1',
   author      = "SWIG Docs",
   description = """Simple swig example from docs""",
   ext_modules = [pointers_module],
   py_modules = ["pointers"],
   )

最后是python主线:

import pointers

result = new_charp()
pointers.conc("Hello ","World!", result);
print(result)
delete_charp(result)

而且都是用终端命令编译的:

swig -c++ -python pointers.i
python setup.py build_ext --inplace 

但是编译器返回错误:

pointers_wrap.cxx: In function ‘char** copy_charp(char*)’:
pointers_wrap.cxx:3124:58: error: invalid static_cast from type ‘char*’ to            
type ‘const char*&’ return (new char *(static_cast< const char *& >(value)));
                                                                         ^
error: command 'gcc' failed with exit status 1

有什么帮助吗?

[更新问题]

按照@MarkTolonen 的建议,我尝试通过以下方式更改 pointers.i 文件:

新文件指针.i:

%module pointers

%
#include "pointers.h"
%

// This input typemap declares that char** requires no input parameter.
// Instead, the address of a local char* is used to call the function.
%typemap(in,numinputs=0) char** (char* tmp) %
  $1 = &tmp;
%

// After the function is called, the char** parameter contains a malloc'ed char* pointer.
// Construct a Python Unicode object (I'm using Python 3) and append it to
// any existing return value for the wrapper.
%typemap(argout) char** %
  PyObject *obj = PyUnicode_FromString(*$1);
  $result = SWIG_Python_AppendOutput($result,obj);
%

// The malloc'ed pointer is no longer needed, so make sure it is freed.
%typemap(freearg) char** %
  free(*$1);
%

// Now that the typemap exists, let swig wrap the header.
%include "pointers.h"

编译:

swig -c++ -python pointers.i
g++ --std=c++11 -fPIC -c pointers.cpp
g++ --std=c++11 -fPIC -c pointers_wrap.cxx -I/usr/local/include/python3.6m

然后我得到了错误:

In function ‘PyObject* _wrap_conc(PyObject*, PyObject*):`
pointers_wrap.cxx:3618:1: error: jump to label ‘fail’ [-fpermissive]
fail:
pointers_wrap.cxx:1222:49: note:   from here
 #define SWIG_fail                  goto fail

pointers_wrap.cxx:2999:68: note: in expansion of macro ‘SWIG_fail’
 #define SWIG_exception_fail(code, msg) do  SWIG_Error(code, msg); SWIG_fail;  while(0)
pointers_wrap.cxx:3603:5: note: in expansion of macro ‘SWIG_exception_fail’
 SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "conc" "', argument " "2"" of type '" "char *""'");

pointers_wrap.cxx:3609:8: note:   crosses initialization of ‘_object* obj’
 auto obj = PyUnicode_FromString(*arg3);
pointers_wrap.cxx:3618:1: error: jump to label ‘fail’ [-fpermissive]
fail:

pointers_wrap.cxx:1222:49: note:   from here
 #define SWIG_fail                     goto fail
pointers_wrap.cxx:2999:68: note: in expansion of macro ‘SWIG_fail’
 #define SWIG_exception_fail(code, msg) do  SWIG_Error(code, msg); SWIG_fail;  while(0)
pointers_wrap.cxx:3598:5: note: in expansion of macro ‘SWIG_exception_fail’
 SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "conc" "', argument " "1"" of type '" "char *""'");

pointers_wrap.cxx:3609:8: note:   crosses initialization of ‘_object* obj’
 auto obj = PyUnicode_FromString(*arg3);

pointers_wrap.cxx:3618:1: error: jump to label ‘fail’ [-fpermissive]
fail:
pointers_wrap.cxx:1222:49: note:   from here
 #define SWIG_fail                   goto fail
pointers_wrap.cxx:3595:62: note: in expansion of macro ‘SWIG_fail’
 if (!PyArg_ParseTuple(args,(char *)"OO:conc",&obj0,&obj1)) SWIG_fail;
pointers_wrap.cxx:3609:8: note:   crosses initialization of ‘_object* obj’
 auto obj = PyUnicode_FromString(*arg3);

它适用于这个 windows 操作系统,但不适用于我的 ubuntu。任何人都可以告诉如何处理它。我真的不知道如何解决我的指针问题。

【问题讨论】:

pointers_wrap.cxx 来自哪里? >单个文件中的 3k 行让我头晕目眩,即使没有看到文件 是的,它是运行文件 setup.py 创建的。它是 swig 自动创建的文件来构建包装文件。在创建 swig 模块时需要它。 【参考方案1】:

来自 SWIG 3.0 文档,接近 §9.2.1 cpointer.i 的末尾:

注意:这些宏都不能用于安全地处理字符串(char * 或 char **)。

因此,您将不得不求助于类型映射。下面是一个例子:

pointers.cpp

我不得不稍微更改您的来源。 char** 参数应该返回分配的指针,而不是释放它:

#include <string.h>
#include <stdlib.h>
#include "pointers.h"

void conc(char *str1, char *str2, char **res)
  *res = (char *)malloc(strlen(str1)+strlen(str2)+1);
  strcpy(*res,str1);
  strcat(*res,str2);

pointers.h

void conc(char *str1, char *str2, char **res);

pointers.i

这个版本的 swig 文件声明了类型映射来处理 char** 输出参数。

%module pointers

%
#include "pointers.h"
%

// This input typemap declares that char** requires no input parameter.
// Instead, the address of a local char* is used to call the function.
%typemap(in,numinputs=0) char** (char* tmp) %
    $1 = &tmp;
%

// After the function is called, the char** parameter contains a malloc'ed char* pointer.
// Construct a Python Unicode object (I'm using Python 3) and append it to
// any existing return value for the wrapper.
%typemap(argout) char** (PyObject* obj) %
    obj = PyUnicode_FromString(*$1);
    $result = SWIG_Python_AppendOutput($result,obj);
%

// The malloc'ed pointer is no longer needed, so make sure it is freed.
%typemap(freearg) char** %
    free(*$1);
%

// Now that the typemap exists, let swig wrap the header.
%include "pointers.h"

test.py

import pointers
result = pointers.conc('Hello ','World!');
print(result)

输出

世界你好!

【讨论】:

谢谢!但是编译您的代码时,我遇到了一些错误,所有错误都在函数PyObject* _wrap_conc(PyObject*, PyObject*) 中引用了jump to label 'fail',并在auto obj = 上注明:crosses initialization of '_object* obj'。你知道为什么吗? @lorsp000 你的 C++ 编译器太旧了。将 auto 更改为 PyUnicodeFromString 的返回类型。我认为是 PyObject*。 我尝试更改返回类型,但仍然不起作用。另一方面,我得到了一个 g++ 6.3.0 版本,对于 PyUnicodeFromString 来说太旧了吗? 不是c++编译器,我只是用命令--str=c++11运行的。 我已经在新答案中更好地解释了这个问题。

以上是关于swig char ** 作为指向 char * 的指针的主要内容,如果未能解决你的问题,请参考以下文章

Swig:char / char* 上的数组和警告

为啥指向 char 的指针与指向 char 作为数组元素的指针的行为不同?

Swig + Lua:调用 m(int argv, char **argc)

如何使用 Swig 将 unsigned char* 转换为 Python 列表?

通过 SWIG 将 Python 3 个字节输入到 C char*

如何定义 swig 类型映射以将 unsigned char* 返回到 java