Boost Python 签名不匹配问题

0 投票
2 回答
2120 浏览
提问于 2025-04-16 19:04

我在把一个方法暴露给Python时遇到了签名不匹配的问题。下面是我的代码:

class StatusEffect
{
public:
   //Virtual functions and non related ommitted
   void AddCancellation(std::string &effect)
   {
       CancelsEffects.insert(effect);
   }
}

在StatusEffect里有一些虚拟方法,我想在我的Python脚本中重写它们,所以我创建了一个类包装器。这个包装器并没有以任何方式重写或改变AddCancellation,我只是简单地展示它以作标记。

struct StatusEffectWrapper : Game::StatusEffects::StatusEffect
{
   //Wrappings for virtual functions here. I don't touch AddCancellation
}

我这样把它暴露给Python:

 class_<StatusEffects::StatusEffect, boost::noncopyable, std::auto_ptr<StatusEffectWrapper> >("StatusEffect")
    .def("AddCancellation", &StatusEffect::AddCancellation)
    ;

在我的Python文件中,我像这样扩展基本的StatusEffect类:

class StatCreepEffect(StatusEffect):
    def __init__(self, name, stat_, rate_, descript, uid, turns, prior, canrefresh, poseffect, cats, conds, flgs, sep, pers, cancels):
        StatusEffect.__init__(self, name, descript, uid, turns, prior, canrefresh, poseffect, cats, conds, flgs, sep, pers)
        self.rate = rate_
        self.stat = stat_
        self.PushCancellations(cancels)
    def PushCancellations(self, cancels):
        for cancel in cancels:
            print (cancel)
            self.AddCancellation(cancel)

Regen = StatCreepEffect("Regen", Stat.HP, 0.05, "Regenerates a small amount of HP every turn", PrimaryEngine.GetUID(), 14, 4, True, True, StatusCategories.SC_Regen, 0, StatusFlags.TickEffect, True, StatusPersistence.SP_Timer_Cure, ["Poison", "Poison-"])

但是,当我这样做时,我收到了以下错误:

Poison
Traceback (most recent call last):
  File "..\..\..\Resources\Scripts\StatusEffects.py", line 27, in <module>
    Regen = StatCreepEffect("Regen", Stat.HP, 0.05, "Regenerates a small amount
of HP every turn", PrimaryEngine.GetUID(), 14, 4, True, True, StatusCategories.S
C_Regen, 0, StatusFlags.TickEffect, True, StatusPersistence.SP_Timer_Cure, ["Poi
son", "Poison-"])
  File "..\..\..\Resources\Scripts\StatusEffects.py", line 11, in __init__
    self.PushCancellations(cancels)
  File "..\..\..\Resources\Scripts\StatusEffects.py", line 23, in PushCancellati
ons
    self.AddCancellation(cancel)
Boost.Python.ArgumentError: Python argument types in
    StatusEffect.AddCancellation(StatCreepEffect, str)
did not match C++ signature:
    AddCancellation(class Game::StatusEffects::StatusEffect {lvalue}, class std:
:basic_string<char,struct std::char_traits<char>,class std::allocator<char> > {l
value})

我不太确定问题出在哪里。StatCreepEffect应该是StatusEffect的一个实例,对吧?而Boost::python不是会自动处理字符串的转换吗?我是不是调用方法的方式不对?感觉像是我漏掉了什么小细节,但我不太确定是什么。任何帮助都将不胜感激。

2 个回答

1

我觉得问题可能出在Boost.Python没有完全理解StatusEffectWrapper是从StatusEffect派生出来的。除非你有特别的理由要指定持有的类型,否则我建议你直接指定类为:

class_<StatusEffects::StatusEffectWrapper, boost::noncopyable>("StatusEffect")
    .def("AddCancellation", &StatusEffectWrapper::AddCancellation)
    ;
2

结果我需要有

void AddCancellation(std::string &effect)
{
   CancelsEffects.insert(effect);
}

作为

void AddCancellation(const std::string &effect)
{
   CancelsEffects.insert(effect);
}

撰写回答