3
$\begingroup$

I'd like to use Blender as a modeling environment for engineering stuff. Blender = python - that is obvious, however I have plenty of functionality for my modeling written in c++ but exported as a c with extern "C". In order to use my c++ functionality in python, I wrap it using ctypes, which works well with python2.7 and python3.5. Generally I use my c++ (with extern "C") functionality with python and ctypes with no problems, but in Blender I have a big problem - it simply crashes when I try to get any value from my c++ shared object. The following two pieces of code recreate the problem:

==== ==== c++ functionality (compiled as libblTest.so) ==== ====

#include <stdio.h>

class KBlenderTest
{
public:
   KBlenderTest(double initVal)
   {
       _val = initVal;
       printf("obj created: initVal: %g\n", _val);  // print to prove that object was created
   }

   ~KBlenderTest()
   {
       printf("obj deleted\n");
   }

  /** function that crashes Blender, but not other instances of python interpreter */
  double get_val()
   {
       return _val;
   }
private:
   double _val;
};

extern "C"
{
    KBlenderTest *KBlenderTest_init(double initVal)
    {
        return new KBlenderTest(initVal);
    }

    void KBlenderTest_del(KBlenderTest *obj)
    {
        delete obj;
    }

    double KBlenderTest_get_val(KBlenderTest *obj)
    {
        return obj->get_val();
    }
}

==== ==== python wrapper for ctypes (blTest.py) ==== ====

import ctypes as ctp

cpp = ctp.cdll.LoadLibrary("path_to_shared_lib/libblTest.so")

cpp.KBlenderTest_get_val.restype = ctp.c_double


class KBlTest(object):
    def __init__(self, initVal):
        self.obj = cpp.KBlenderTest_init(ctp.c_double(initVal))

    def get_val(self):
        return cpp.KBlenderTest_get_val(self.obj)

    def __del__(self):
        cpp.KBlenderTest_del(self.obj)


def test(initVal):
    test = KBlTest(initVal)
    print("test=", test.get_val())

In linux shell python I run the test with:

import sys
sys.path.append("path_to_python_wrapper/")
import blTest

blTest.test(1.23)

which gives the following output:

obj created: initVal: 1.23
test= 1.23
obj deleted

Exactly the same action in Blender's python console, crashes Blender with segmentation fault. Currently I use Blender 2.79, but the situation was exactly the same with a few versions back.

Has anyone had similar problem? The functionality I have in mind is much more complex, but I've tracked it down to a relatively simple case. I would be grateful for some clues how deal with this.

Best wishes, Jerzy

$\endgroup$
  • $\begingroup$ Instant upvote for having made a minimal example! Have you tried building a debug build of Blender yourself, so you can see what's going on? $\endgroup$ – dr. Sybren Oct 16 '17 at 7:31
  • $\begingroup$ No, I haven't done so yet. I was hoping, that there is someone, who has successfully struggled with a case like this. I'll try do the debugging soon, but my problem is that I really need to model something soon. $\endgroup$ – Lendzian Oct 16 '17 at 9:04
1
$\begingroup$

You also need to specify the arg types, e.g.

cpp.KBlenderTest_get_val.argtypes = (ctp.c_void_p,)

otherwise I think they default to int, which is the wrong size for a pointer on 64-bit architectures.

Also, I would recommend opening the .so file with its full name including version number, e.g.

cpp = ctp.cdll.LoadLibrary("path_to_shared_lib/libblTest.so.1")

This is because it is usual to increment the version suffix if/when the ABI changes in some backward-incompatible way, so you want to make sure you stay with the right version, at least until your Python wrapper gets updated to the newer version in future.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.