Saturday, April 18, 2015

Unreal Engine4 - CPython Plugin


Rusthon has special syntax for directly using PyObject's from the CPython CAPI. The -> operator is used on PyObject's, and is transpiled into: PyObject_GetAttrString(ob,name), for more info see this wiki page. This allows you to directly manage calling CPython functions, cast and move data back and forth from C++ to the CPython interpreter. This makes using complex libraries simple and safer, you do not need to depend on complex wrapper generators, or depend on C++ reflection to dynamically bind CPython to C++.

Unreal has a C++ reflection system, and this can be used to generate bindings to a scripting language. Unreal users want scripting support, see this thread, and this one asking about CPython in Unreal.

Scripting is great when you have a command-prompt and can type code at runtime, or write quick scripts and simply run them. Scripting fails when you need to do something complex and use multiple threads, for this you need C++. Rusthon allows you to write in a Python-like language and create fast glue code that bridges CPython together with any other C++ library, no reflection or generated bindings required.

This example: unreal_cpython.md shows you how to connect CPython2.7 with Unreal. The example contains no handwritten C++, instead the code is transpiled to C++ at compile time. The embedded Python script is also inlined into the final binary.

Friday, April 17, 2015

C++ Backend Part3


Calling into C++ from another language normally requires an FFI and writing extra broiler plate code and having to worry about garbage collection and threading issues. Just take a look at how fucked up interfacing D is with C++. Don't miss the bottom of that doc on C++ Templates, from the doc: "D templates have little in common with C++ templates, and it is very unlikely that any sort of reasonable method could be found to express C++ templates in a link-compatible way with D. This means that the C++ STL, and C++ Boost, likely will never be accessible from D." There are many other system languages, like Rust, that want to kill off C++, but do not have a good way of interfacing with C++.

C++ is deeply entrenched, its not going anywhere. Rusthon transpiles to human readable C++, and you can configure the transpiler to use regular or smart pointers. Interfacing with an external C++ library is simple and requires no FFI, you can use C++ namespaces, template classes (via macros) and directly handle memory, passing the address of some variable or returning a pointer.

Caffe Deep Learning

Caffe is a large deep learning framework with many different types of neural networks. Getting it to compile and working on Fedora took me a couple of days, along the way I had to make lots of notes on the build and defines it required. The notes, build script, and code is all put into a single markdown file, see hello_caffe.md.

Testing Caffe with Rusthon has given me the chance to iron out the last details for working with external C++. Some functions in Caffe need to be passed the address of a variable, not the value or a pointer to it, the new builtin addr(X) takes the address of X and passes it to the function. If you need to initialize an array of template classes you can now use this trick.

with MyType as "some_template<float>":
    x = new( MyType() )
    y = []MyType()
    y.append( x )

Wednesday, April 8, 2015

C++ Backend Part2


New syntax and built-in functions have been added to Rusthon's C++ transpiler to make interfacing with external C++ libraries as simple as possible. Namespace syntax is supported using ::, just like in normal C++, more info here. Macro syntax is support with the macro function (to inline simple macros) and new with statement with T as "foo(%s)": that makes T a callable macro, this is useful for calling template functions from external libraries, more info see here.

Functions can also now use C++ type syntax to define the function return type. This allows you to override the default behavior of returning shared pointers (to objects, arrays, and maps).

  • def f()->T* returns a pointer to T
  • def f()->T& returns a reference to T

Calling methods on strings has now been fixed and always works, before there was the problem of pointers|references (which the transpiler had to keep track of). This has been fixed with a c++ template class function, the transpiler when it is not sure what the type of something is will use this template function to properly wrap the value. This also solves the general problem of working with objects from external c++ libs, where you are not sure if something is a pointer, or a pointer to something.