带有内联指令的 SWIG、Python 和接口文件 [英] SWIG, Python and interface file with inline directive

查看:23
本文介绍了带有内联指令的 SWIG、Python 和接口文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have Ubuntu-20.04, Anaconda-3 (installed into the user dir) with Python-3.7.9 and 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'

然而,如果我写一个更长的接口文件一切都好:

However, if I write a longer interface file everything is OK:

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

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

UPD @Jens suggested to replace # with % in the first (short) interface file. In this case I got

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

推荐答案

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

%inline both includes the braced code directly in the SWIG-generated wrapper code, but also processes it to generated target language interfaces. So this:

%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 被包含和处理,我做了:

To show that %inline is both included and processed, I made:

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

上面做了正确的事情并暴露了接口,但比仅使用更糟糕:

The above did the right thing and exposed the interface, but it's worse than just using:

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

%inline 真正用于将新函数插入包装器并暴露接口,例如:

%inline is really for inserting new functions into the wrapper and exposing the interface, such as this:

%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();
};

这篇关于带有内联指令的 SWIG、Python 和接口文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆