10 March 2009

Lessons learned of the evening

To make a long story short, or more precisely, to summarize an hour of frustration: when using SWIG with Python, watch that you actually instantiate an object by calling its constructor, because apparently you can change the values of the class itself without creating an object from it. Then, when you later want to pass an instantiated object to another C++ method, it won't fail with an inscrutable error. You probably don't want to read the rest of this post, but it's preserved for posterity.

I have a struct of data, SourceDataUniform, that I pass to a class called RadiationController. My original code was:
newSource = ImcTransport.SourceDataUniform
newSource.emissionRate = 2.0
newSource.cellIndex = 1

but this failed with TypeError: in method 'RadiationControllerT_addUniformSource', argument 2 of type 'iMc::SourceDataUniform'. Yet I could print the data in the object, and it said it was of type <class 'ImcTransport.SourceDataUniform'>.

I knew I'd gotten the exact same thing to work with a different class, so I wasn't sure if the problem was that I was using a struct, or what.

I spent a good while looking through the SWIG documentation on proxy classes, structs, the ".this" method. Eventually, noting that the similar case that actually worked gave a repr of <ImcPhysics.OpacityModelConstant; proxy of <Swig Object of type 'iMc::OpacityModelConstant *' at 0x305670> >, and realizing that the "this" object was only set in the constructor for the SourceDataUniform Python wrapper, I discovered that I wasn't instantiating an object. Adding parentheses
newSource = ImcTransport.SourceDataUniform()
solved the problem.


Post a Comment