2011-05-25 60 views
0

我有一些類函數需要通過指針參數。但是,當我暴露並覆蓋boost :: python中的這些函數時,我對參數所做的任何更改都不會反射回原始內容,這意味着它不會像我期望的那樣被指針傳遞。舉個例子,我的意思是,這裏是我的一些代碼,其中沒有重要的功能和細節。不能更改傳遞給python函數的對象boost :: python

class StatusEffect 
{ 
public: 
     virtual void TickCharacter(Character::BaseCharacter* character, Battles::BattleField *field, int ticks = 1); 
} 
//In my Scripting Code header file 

struct StatusEffectWrapper : Game::StatusEffects::StatusEffect 
{ 
    virtual void TickCharacter(Game::Character::BaseCharacter* character, Game::Battles::BattleField *field, int ticks = 1); 
    virtual void TickCharacterDefault(Game::Character::BaseCharacter* character, Game::Battles::BattleField *field, int ticks = 1); 
} 
//In the actual scripting code 
    void StatusEffectWrapper::TickCharacter(Game::Character::BaseCharacter* character, Game::Battles::BattleField *field, int ticks) 
    { 
     call_method<void>(self, "TickCharacter", character, field, ticks); 
    } 
    void StatusEffectWrapper::TickCharacterDefault(Game::Character::BaseCharacter* character, Game::Battles::BattleField *field, int ticks) 
    { 
     this->StatusEffect::TickCharacter(character, field, ticks); 
    } 

    class_<StatusEffects::StatusEffect, boost::shared_ptr<StatusEffectWrapper> >("StatusEffect") 
    .def("TickCharacter", &StatusEffect::TickCharacter, &StatusEffectWrapper::TickCharacterDefault) 

終於在我的Python文件,我嘗試做這樣的事情

class StatCreepEffect(StatusEffect): 
    #rate = 0.075 
    #stat = Stat.HP 
    def __init__(self, name, stat_, rate_, descript, uid, turns, prior, canrefresh, poseffect, cats, conds, flgs, sep, pers): 
     StatusEffect.__init__(self, name, descript, uid, turns, prior, canrefresh, poseffect, cats, conds, flgs, sep, pers) 
     self.rate = rate_ 
     self.stat = stat_ 
    def TickCharacter(self, Character, Field, Ticks): 
     if (self.stat == Stat.HP): 
      Character.SetHP(int(round(Character.GetHP() + Character.GetInBattleStat(self.stat) * self.rate))) 
      print("HP Regenerated on character " + Character.GetName() + " New HP: " + str(Character.GetHP())) 
     elif (self.stat == Stat.MP): 
      Character.SetMP(int(round(Character.GetMP() + Character.GetInBattleStat(self.stat) * self.rate))) 
     elif (self.stat == Stat.SP): 
      Character.SetSP(int(round(Character.SetSP() + Character.GetInBattleStat(self.stat) * self.rate))) 

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

SELibrary.AddPythonEffect(Regen); 

我打電話喜歡的效果所以在我的C++代碼

StatusEffect* regen = game.GetSELibrary().GetStatusEffect(std::string("Regen")); 
while(character.GetHP() < 600) 
    { 
regen->TickCharacter(&character, &field, 1); 
     std::cout << "Character HP: " << character.GetHP() << std::endl; 
    } 

我創造了這個代碼如下這裏的示例http://wiki.python.org/moin/boost.python/OverridableVirtualFunctions

腳本編譯並且效果添加正確。 python腳本中的打印行打印正確的值。字符對象以400 HP和打印行輸出430開頭。但是,我的C++代碼中的std :: cout行總是輸出400,這意味着腳本添加的額外30 HP不會反映回原始對象。爲了清楚起見,這裏是從上面的C++代碼片段的控制檯輸出:

HP Regenerated on character Arian New HP: 430 
Character HP: 400 

我最初擁有的一切作爲傳遞按引用而不是指針,但我希望切換到指針將解決這個問題。它沒有。

有人可以幫我弄清楚如何使這項工作正確嗎?這將不勝感激。

感謝

編輯:

如果它的事項,該AddPythonEffect定義如下:

void StatusEffectsLibrary::AddPythonEffect(boost::shared_ptr<StatusEffect> effect) 
{ 
    if (effect.get() != nullptr) 
    { 
     NameToSEMap[effect->GetName()] = effect; 
     IDToSEMap[effect->GetUID()] = effect; 
    } 
} 

回答

2

你看到的行爲是因爲加速的Python副本C++實例,然後會與您在C++庫中保存的實例斷開連接。這可以通過更改class_<T, Bases, HeldType, NonCopyable>實例中的「HeldType」來定製。 See the Boost documentation for more information.請注意,HeldType的默認類型爲T,因此您的類型將按值(複製)保存。

如果HeldType是某種智能指針(boost::shared_ptrboost::intrusive_ptr),尤其是從生命週期管理的角度來看,這是最簡單的。我相信你可以使用原始指針,但是生命週期管理變得非常棘手(當Python知道你的C++對象已經被銷燬了,同樣,你的C++庫在什麼時候知道Python何時不再引用它?) 。

+0

我討厭打擾你,但我還不清楚我到底需要做什麼。 StatusEffectWrapped作爲持有的類型正確?我如何修改它以完成此項工作?我將它封裝到shared_ptr中,但沒有任何效果。我需要公開shared_ptr嗎?對不起,我只是有點困惑 – Megatron 2011-05-25 03:05:04

0

我覺得這個問題實際上是在

class_<StatusEffects::StatusEffect, boost::shared_ptr<StatusEffectWrapper> >("StatusEffect") 

不同的聲明類和指針類型,我建議class_<StatucEffectsWrapper,boost::shared_ptr<StatusEffectWrapper> >("StatusEffect"),至少這是我在my code其中工程做(的對象不是通過shared_ptr傳遞這種情況下,但我認爲這不會有所作爲)。