Избегайте ошибки «ничего не известно о [parent] class ...» в swig - PullRequest
4 голосов
/ 19 декабря 2010

Допустим, у меня есть два класса A в заголовочном файле Ah

// A.h
class A {
public:
  void foo();
};

и B в заголовочном файле Bh

// B.h
class B : public A {
public:
  void bar()
};

Я хочу создать оболочку Swig для класса B.Файл интерфейса выглядит следующим образом.

B.i
%{
#include "B.h"
%}

%include B.h

При запуске swig он выходит с сообщением об ошибке «ничего не известно об A», что ясно, поскольку B наследуется от A и, следовательно, swig должен знать об A для генерацииинтерфейс.Предположим далее, что в Ah есть какой-то материал, синтаксический анализатор swig не может выполнить синтаксический анализ и выдает ошибку, когда видит этот материал.Я вдруг решаю, что на самом деле мне нужен не только бар в интерфейсе, но и не foo.Есть ли способ сказать Swig, что он на самом деле не смотрит на А, поскольку мне действительно не нужны вещи, которые В наследует от А?

Ответы [ 2 ]

3 голосов
/ 25 июля 2012

Вы можете использовать% import для базового класса.Это позволяет SWIG знать о классе, но обертки генерироваться не будут.Из документации SWIG 2.0 :

Если какой-либо базовый класс не определен, SWIG все еще генерирует правильные отношения типов.Например, функция, принимающая Foo *, будет принимать любой объект, полученный из Foo, независимо от того, на самом ли деле SWIG обернул класс Foo. Если вы действительно не хотите создавать оболочки для базового класса, но хотите отключить предупреждение, вы можете рассмотреть возможность использования директивы% import для включения файла, определяющего Foo.% import просто собирает информацию о типе, но не генерирует оболочки. В качестве альтернативы вы можете просто определить Foo как пустой класс в интерфейсе SWIG или использовать подавление предупреждений.

3 голосов
/ 19 декабря 2010

Я собрал пример и получил только предупреждение о том, что ничего не известно об A. Расширение все еще прекрасно работает и может вызывать foo () B, не зная о bar () A. Вот мой пример создания расширения Python для Windows:

Построить вывод

C:\example>nmake /las
b.cpp
a.cpp
Generating Code...
   Creating library b.lib and object b.exp
B.h(12) : Warning 401: Nothing known about base class 'A'. Ignored.
b_wrap.cxx
   Creating library _b.lib and object _b.exp

Пример использования

Python 2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import b
>>> b.B().bar()
In B::bar()
>>> b.B().foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "b.py", line 73, in <lambda>
    __getattr__ = lambda self, name: _swig_getattr(self, B, name)
  File "b.py", line 54, in _swig_getattr
    raise AttributeError(name)
AttributeError: foo

Файлы

хиджры

#pragma once

#ifdef DLL_EXPORTS
    #define DLL_API __declspec(dllexport)
#else
    #define DLL_API __declspec(dllimport)
#endif

class DLL_API A
{
public:
    void foo();
};

b.h

#pragma once

#ifdef DLL_EXPORTS
    #define DLL_API __declspec(dllexport)
#else
    #define DLL_API __declspec(dllimport)
#endif

#include "a.h"

class DLL_API B : public A
{
public:
    void bar();
};

a.cpp

#include <stdio.h>
#define DLL_EXPORTS
#include "a.h"

void A::foo()
{
    printf("In A::foo()\n");
}

b.cpp

#include <stdio.h>
#define DLL_EXPORTS
#include "b.h"

void B::bar()
{
    printf("In B::bar()\n");
}

b.i

%module b

%begin %{
#pragma warning(disable:4100 4127 4706)
%}

%{
#include "B.h"
%}

%include <windows.i>
%include "B.h"

Makefile

_b.pyd: b.dll b_wrap.cxx
    cl /nologo /EHsc /LD /W4 b_wrap.cxx /I c:\Python26\include /Fe_b.pyd -link /nologo /libpath:c:\Python26\libs b.lib

b_wrap.cxx: b.i
    swig -c++ -python b.i

b.dll: a.cpp b.cpp
    cl /nologo /LD /W4 b.cpp a.cpp
...