SwigRapped Python生成的包装器不返回代理对象

2024-09-30 22:19:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用SWIG为一些C++生成Python包装器。在生成的python包装器中,返回std::shared_ptr对象的函数返回原始类型而不是python代理对象,例如:

@staticmethod
def GetDerivedObject() -> "EP::DerivedPtr":
...

代码运行正确,我能够在这些对象上调用预期的方法。但是,因为返回的对象不是代理,所以各种事情在IDE中都不起作用,例如导航和代码完成

手动更改生成的包装中的公共函数以返回代理可以修复IDE问题。通过此更改,代码仍能正确运行

@staticmethod
def GetDerivedObject() -> Derived:
...
# Leaving the _PythonWrapper function still returning EP::DerivedPtr:
def Program_GetDerivedObject() -> "EP::DerivedPtr":
    r"""Program_GetDerivedObject() -> EP::DerivedPtr"""
    return _PythonWrapper.Program_GetDerivedObject()

虽然上面的编辑似乎在一个小例子中起作用,但我担心它可能会产生负面影响,例如,在一个更大的项目中可能会出现问题的拷贝或泄漏。如果这个更改是正确的,我想从模板控制它

这里最简单的例子再现了这个问题

标题:

#pragma once

#include <memory>
    
namespace EP
{
    class Base
    {
    public:
        Base();
        virtual void Action();
    };
    
    class Derived : public Base
    {
    public:
        Derived();
        void DerivedOnlyAction();
    };

    typedef std::shared_ptr<Base> BasePtr;
    typedef std::shared_ptr<Derived> DerivedPtr;
    
    class Program
    {
    public:
        static BasePtr GetBaseObject();
        static DerivedPtr GetDerivedObject();
    
    private:
        static DerivedPtr m_derived;
    };
}

Cpp:

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

EP::DerivedPtr EP::Program::m_derived;
   
EP::Base::Base() {}
    
void EP::Base::Action()
{
    std::cout << "Action (base)" << std::endl;
}

EP::Derived::Derived() {}
    
void EP::Derived::DerivedOnlyAction()
{
    std::cout << "Action (derived only)" << std::endl;
}

EP::BasePtr EP::Program::GetBaseObject()
{
    return GetDerivedObject();
}
    
EP::DerivedPtr EP::Program::GetDerivedObject()
{
    if (!m_derived)
    {
        m_derived = std::make_shared<Derived>(*(new Derived()));
    }
    return m_derived;
}

SWIG命令行:

"D:\package_repo\swigwintools.4.0.0\tools\swigwin-4.0.0\swig.exe" -outdir "..\PythonWrapper" -c++ -python -py3 "$(ProjectDir)\PythonWrapper.i"

SWIG接口:

%module PythonWrapper
    
%include "typemaps.i"
%include <std_shared_ptr.i>
    
%feature("autodoc", "2");
    
%{
#include "Example.h"
    
using namespace std;
using namespace EP;
%}
    
%feature("docstring") EP::Base::Action "Performs a base action"
%feature("docstring") EP::Derived::DerivedOnlyAction "Performs a derived-only action"
    
%shared_ptr(EP::Base);
%shared_ptr(EP::Derived);
    
%include "..\ExampleProject\Example.h"
    
namespace EP
{
    typedef std::shared_ptr<Base> BasePtr;
    typedef std::shared_ptr<Derived> DerivedPtr;
}

Python客户端:

from PythonWrapper import *
    
# Code completion works on Project
baseObj = Program.GetBaseObject()
derivedObj = Program.GetDerivedObject()
    
# No code completion on these objects
baseObj.Action()
derivedObj.DerivedOnlyAction()

我将SWIG 4.0.0与Python 3.6一起使用

谢谢你的建议


Tags: 对象baseincludeactionprogramswigepshared