【问题标题】:SWIG, Python and interface file with inline directive带有内联指令的 SWIG、Python 和接口文件
【发布时间】:2021-10-12 10:35:23
【问题描述】:

我有 Ubuntu-20.04、Anaconda-3(安装到用户目录中)和 Python-3.7.9 和 SWIG-4.0。

这是我的文件。

a.h:

void foo(void);

a.c:

#include <stdio.h>
#include "a.h"
void foo(void) { printf("Foo!\n"); }

a.i:

%module a
%inline %{
#include "a.h"
%}

test.py:

import a
a.foo()

编译脚本compile.sh:

A=$HOME/opt/anaconda3
I=$A/include/python3.7m
gcc -c -fpic -DHAVE_CONFIG_H -I$I a.c
$A/bin/swig -python -py3 a.i
gcc -c -fpic -DHAVE_CONFIG_H -I$I a_wrap.c
gcc -shared a.o a_wrap.o -o _a.so

编译后测试脚本产生

Traceback (most recent call last):
  File "test.py", line 2, in <module>
    a.foo()
AttributeError: module 'a' has no attribute 'foo'

但是,如果我写一个更长的接口文件,一切都OK:

%module a
%{
#include "a.h"
%}
%include "a.h"

UPD @Jens 建议在第一个(短)接口文件中将 # 替换为 %。在这种情况下,我得到了

a_wrap.c:2701:1: error: expected identifier or '(' before '%' token
 2701 | %include "a.h"
      | ^
a_wrap.c:2720:12: error: '_wrap_foo' undeclared here (not in a function)
 2720 |   { "foo", _wrap_foo, METH_NOARGS, NULL},
      |            ^~~~~~~~~
gcc: error: a_wrap.o: No such file or directory

【问题讨论】:

  • 在您的帖子中描述您在第一次运行时如何调用 swig 以及您正在采取哪些步骤来编译示例是有意义的。正如您所说,对于较长的接口文件一切正常,可能在那里找到原因。
  • 你需要%include 让 SWIG 知道 foo
  • @amo-ej1:完成。

标签: python c swig


【解决方案1】:

%inline 既直接在 SWIG 生成的包装器代码中包含大括号代码,也将其处理为生成的目标语言接口。所以这个:

%module a
%inline %{
void foo(void);
%}

相当于:

%module a
%{
void foo(void) {}
%}
void foo(void) {}

但是这个:

%module a
%inline %{
#include "a.h"
%}

相当于:

%module a
%{
#include "a.h"
%}
#include "a.h"  // NOT the same as %include "a.h" and isn't processed for interfaces

为了表明 %inline 被包含和处理,我做了:

%module a
%inline %{
#include "a.h"   // ignored in "include-in-wrapper" pass
#ifdef SWIG
%include "a.h"   // processed in "wrap-with-SWIG" pass
#endif
%}

上面做对了,暴露了界面,但比仅仅使用更糟糕:

%module a
%{
#include "a.h"
%}
%include "a.h"

%inline 真正用于在包装器中插入新功能并暴露接口,例如:

%module a
%inline %{
class myClass
{
private: 
  int a;
public: 
  myClass(){} 
  void foo(){}
};
%}

否则你必须至少写:

%module a

%{ // new functionality added to wrapper
class myClass
{
private: 
  int a;
public: 
  myClass(){} 
  void foo(){}
};
%}

class myClass   // process the interface
{
public:         // note don't need to repeat private part or
  myClass();    // implementation, just public declarations to be exposed.
  void foo();
};

【讨论】:

  • 谢谢你,@Mark,现在很干净。不明白为什么 SWIG 在这两种情况下都没有使用 # 前缀,尤其是因为所有这些都是关于 C/C++ 的。
  • @EvgenyP.Kurbatov SWIG 处理指令以 % 开头,即使有些看起来像,也不是 C/C++。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多