3

This could be something simple I'm missing but I can't find any explanation.

Given an abstract class, which is implemented elsewhere and its interface provided by an exported function:

class IFoo {
public:
    virtual ~IFoo(){}
    virtual void bar()=0;
};

extern IFoo* get_interface();

In c++ I would use this as:

IFoo* foo = get_interface();
foo->bar();

If I SWIG this, I can import the module and assign get_interface() to a variable:

import myfoo
foo = myfoo.get_interface()

But I can't access foo.bar():

>>> foo.bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'SwigPyObject' object has no attribute 'bar'

What am I missing?

Thanks!


Here is the full thing if the fragments above aren't clear enough:

The *.i file:

%module myfoo
#define SWIG_FILE_WITH_INIT

%include "myfoo.h"
%{
#include "myfoo.h"
%}

The myfoo.h header:

class IFoo {
public:
    virtual ~IFoo(){}
    virtual void bar()=0;
    virtual void release()=0;
};

extern IFoo* get_interface();

The implementation file (myfoo.cpp)

#include "myfoo.h"
#include <iostream>

class Foo : public IFoo {
public:
    Foo(){}
    ~Foo(){}
    void bar();
    void release();
};

void Foo::bar() {
    cout << "Foo::bar()..." << endl;
}

void Foo::release() {
    delete this:
}

IFoo* get_interface() {
    return new Foo();
}
1
  • You need %feature("director") IFoo, but I think you're missing something additional too. Can you include all of a complete minimal example rather than just selected fragments? Commented Jan 30, 2014 at 20:33

2 Answers 2

2

I found the problem. I had this within a build system generating a Ruby extension. When I decided to add Python bindings, I just added a new (Xcode) target generating it just as I was doing for the Ruby extension. What I didn't realize was that swig also generates a module.py file with all the initialization code (unlike Ruby). Once I found that, I simply moved the generated python file along with the extension dynamic library file and imported it instead. It all works now.

I found that by actually creating the above myfoo code by hand (as opposed to running my build system, which ignored the extra myfoo.py file alltogether). Once I run swig by hand, I noticed it generated not only myfoo_wrapp.cpp but also myfoo.py.

Thanks for the effort. For future reference, this has nothing to do with directors (I'm not trying to create a two-way interface). It was simply not knowing about the extra python initialization code generated by swig.

Before:

myfoo.i
myfoo.h
myfoo.cpp

>swig -c++ -python myfoo.i

After:

myfoo.i
myfoo.h
myfoo.cpp
myfoo.py    <== Missed this one
myfoo_wrap.cxx
Sign up to request clarification or add additional context in comments.

1 Comment

+1 for finding solution and posting. You should accept it (if you can, can't remember).
0

Check that you have "directors" turned on in your .i file for your module:

%module(directors="1") myfoo

This is discussed in section 34.5 "Cross language polymorphism" of SWIG docs. If it is already on, put a comment and I will take a closer look.

1 Comment

Yes, I had added that earlier based on some results I found on google but it had no effect. I've edited the question itself to show the module declaration in the *.i file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.