class 的 Swig 包装器继承自专门的模板类型导致缺少方法

Swig wrapper for class inheriting from specialized template type results in missing methods

我正在使用 Swig 1.4.1 为 C# 项目包装一些 C++ 代码。
考虑一个文件中的以下代码 Foo.h.

#ifndef __Foo__
#define __Foo__

namespace Ogre
{
    template<int foo, typename T> class FooBase
    {
    public:

        int getFooBase() const
        {
            return 1;
        }
    };

    struct FooSpecialized : public FooBase<4, double>
    {
        int getFooSpecialized() const
        {
            return 2;
        }
    };

    class FooImpl : public FooSpecialized
    {
    public:
        int getFooImpl() const
        {
            return 3;
        }
    };
}

#endif

为此,我在我的 Swig 接口文件中使用了以下内容。

%include "Foo.h"

因此,我可以访问方法 getFooSpecialized()getFooImpl()。但是 getFooBase() 不见了。

我在编译我的 Swig 接口文件时没有警告

通过查看生成的 C# 文件可以很容易地看出这一点。有一个文件 FooSpecialized.cs 其中包含

public class FooSpecialized : global::System.IDisposable {
  ...

  public int getFooFooSpecialized() {
    int ret = OgrePINVOKE.FooSpecialized_getFooFooSpecialized(swigCPtr);
    if (OgrePINVOKE.SWIGPendingException.Pending) throw OgrePINVOKE.SWIGPendingException.Retrieve();
    return ret;
  }
}

FooImpl.cs其中包含

public class FooImpl : FooSpecialized {
  ...

  public int getFooImpl() {
    int ret = OgrePINVOKE.FooImpl_getFooImpl(swigCPtr);
    if (OgrePINVOKE.SWIGPendingException.Pending) throw OgrePINVOKE.SWIGPendingException.Retrieve();
    return ret;
  }
}

到目前为止,我尝试了 %rename%template,但没有用。 我还阅读了有关拆分文件的信息,但这对我来说不是一个选项,因为它是我正在使用的第三方组件。

关键是%template的用途和位置。按原样使用您的 Foo.h,以下 test.i 文件有效:

%module test

%{
#include "Foo.h"    // Adds Foo.h to the generated code.
%}

// Declare to SWIG the FooBase class interface.
namespace Ogre
{
    template<int foo, typename T> class FooBase
    {
    public:
        int getFooBase() const;
    };

// Now that SWIG knows the template, declare an instantiation of
// the template you want to use.
%template(FooBase4dbl) FooBase<4,double>;

// Declare the class interfaces that uses the template instance

    struct FooSpecialized : public FooBase<4, double>
    {
        int getFooSpecialized() const;
    };

    class FooImpl : public FooSpecialized
    {
    public:
        int getFooImpl() const;
    };
}

如果您愿意,可以重构 header 以减少代码重复:

FooBase.h

#ifndef __FooBase__
#define __FooBase__

namespace Ogre
{
    template<int foo, typename T> class FooBase
    {
    public:
        int getFooBase() const
        {
            return 1;
        }
    };
}

#endif

Foo.h

#ifndef __Foo__
#define __Foo__

#include "FooBase.h"

namespace Ogre
{
    struct FooSpecialized : public FooBase<4, double>
    {
        int getFooSpecialized() const
        {
            return 2;
        }
    };

    class FooImpl : public FooSpecialized
    {
    public:
        int getFooImpl() const
        {
            return 3;
        }
    };
}

#endif

test.i

%module test

%{
#include "Foo.h"
%}

%include "FooBase.h"
%template(FooSpec) Ogre::FooBase<4,double>;
%include "Foo.h"

演示(我为 Python 设置):

>>> import test
>>> f=test.FooImpl()
>>> f.getFooBase()
1