[Python] Call in python to a constructor of a C++ class exported through SWIG using a...

Discussão em 'Python' iniciado por Stack, Setembro 27, 2024.

  1. Stack

    Stack Membro Participativo

    Here is a minimal example.

    I have the following SWIG interface file (all-in-one)

    pyhello.i

    %module pyhello

    %{
    #include <iostream>

    // Inline definition of my C++ class
    class MyInt
    {
    public:
    MyInt(int n) : _n(n) {}

    static MyInt* create(int n) { return new MyInt(n); }

    int get() const { return _n; }

    private:
    int _n;
    };
    %}

    %typemap(out) MyInt, MyInt&
    {
    std::cout << "%typemap(out) MyInt, MyInt&" << std::endl;
    $result = PyLong_FromLongLong($1.get()); // $1 is an object or a reference
    }

    %typemap(out) MyInt*
    {
    std::cout << "%typemap(out) MyInt*" << std::endl;
    $result = PyLong_FromLongLong($1->get()); // $1 is a pointer
    }

    // Export MyInt (only public stuff is needed here)
    class MyInt
    {
    public:
    MyInt(int n);

    static MyInt* create(int n);

    int get() const;
    };


    I compile it (under Ubuntu 22.04, g++ 11.4.0, python 3.10.12 and SWIG 4.2.0) using these two commands:

    swig -c++ -python -o pyhello_wrap.cpp pyhello.i

    g++ -fpic -shared pyhello_wrap.cpp `python3-config --cflags` -o _pyhello.so


    Then I run the following python script:

    from pyhello import *

    i1 = MyInt.create(5)
    print(type(i1))
    print(i1)

    i2 = MyInt(6)
    print(type(i2))
    print(i2)
    print(i2.get()) # This one fails


    ...which produces the following output:

    %typemap(out) MyInt*
    <class 'int'>
    5
    %typemap(out) MyInt*
    <class 'pyhello.MyInt'>
    <pyhello.MyInt; proxy of 6 >
    Traceback (most recent call last):
    File "/****/test_pyhello.py", line 10, in <module>
    print(i2.get())
    File "/****/pyhello.py", line 73, in get
    return _pyhello.MyInt_get(self)
    TypeError: in method 'MyInt_get', argument 1 of type 'MyInt const *'


    My questions:

    1. Why the call to the constructor MyInt creates an invalid MyInt object in Python (we see that the typemap is used to obtain an integer and then the integer is wrapped into a fictive MyInt python object)?
    2. Is there any way to have a typemap(out) for MyInt so that 'create' returns native integers while having a constructor of MyInt which keeps creating proxy objects (as if there was no typemap)?

    Thank you for your help!

    Continue reading...

Compartilhe esta Página