Setting up an 'environment' for an embedded Lua Script - c++

I am embedding a Lua interpreter in a C++ application.
I want to setup an 'environment' for running scripts, such that certain variables are made available to all scripts.
For example, I want to expose READ ONLY objects Foo and FooBar to scripts, such that Foo and FooBar are available to all running scripts.
Does anyone know how I can do this?. A snippet to show how to so this would be very useful.

I haven't heard of read-only variables in Lua but you can prevent modification by making the environment available via a function call instead.
If the C++ application is large, you will probably want to use a tool to generate an interface you can call from Lua. I have used tolua++ in the past with some luck:
Suppose demo.hpp is a header file of the C++ application:
#ifndef SO_DEMO_HPP
#define SO_DEMO_HPP
namespace demo
{
class Foo
{
double x;
public:
Foo(double x) : x(x) {}
double getX() const { return x; }
};
Foo* getFoo();
}
#endif
Implement demo::getFoo() in demo.cpp.
demo.pkg lists the things that should be callable from Lua:
$#include "demo.hpp"
namespace demo
{
class Foo
{
double getX() const;
};
Foo* getFoo();
}
Generate demo_stub.cpp and demo_stub.hpp files containing our Lua module:
$ tolua++5.1 -o demo_stub.cpp -H demo_stub.hpp demo.pkg
main.cpp is a Lua interpreter that loads the demo module:
#include "demo.hpp"
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <tolua++.h>
}
#include "demo_stub.hpp"
int main()
{
lua_State *L = lua_open();
luaL_openlibs(L);
tolua_demo_open(L);
if (luaL_dofile(L, NULL) != 0)
fprintf(stderr, "%s\n", lua_tostring(L, -1));
lua_close(L);
return 0;
}
The tolua_demo_open() function was generated by tolua++ and is declared in demo_stub.hpp.
Build a Lua interpreter named demo:
$ g++ -I/usr/include/lua5.1 demo.cpp demo_stub.cpp main.cpp -ltolua++5.1 -llua5.1 -o demo
Construct a demo.lua script
print("Hello, world!")
print(tolua.type(demo.getFoo()))
print(demo.getFoo():getX())
and feed the script to the interpreter:
$ ./demo < demo.lua
Hello, world!
demo::Foo
42

lua_setglobal.
As for 'read only', do you mean that that Foo will not be overwritable (e.g. Foo = 10), or that the value Foo reverse will be immutable (e.g. Foo.x = 10)?

Related

How to destruct C++ class inside package.preload function

I'm using C++ classes in Lua which I wrapped using SWIG.
Since I'm using a single Lua_State, I would like to be able to free variables in a specific chunk of Lua script without calling lua_close(L).
I decided to use package.preload['name'] so a chunk can be accessed from other chunk by using require 'name' when needed.
And I was told that the variables inside package.preload function are freed after I do the following:
package.preload['name'] = nil
package.loaded['name'] = nil
However, it seems my custom C++ classes are not destructed even after this.
Here's my full example code:
In Main.cpp
#include "Main.h"
int main()
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
luaopen_my(L);
lua_settop(L, 0);
luaL_dostring(L, "package.preload['test'] = function ()\n"
"local test = {}\n"
"local class = my.Class()\n"
"return test\n"
"end\n");
luaL_dostring(L, "require 'test'");
luaL_dostring(L, "package.preload['test'] = nil\n"
"package.loaded['test'] = nil\n");
}
In Main.h
#include "lua.hpp"
extern "C"
{
int luaopen_my(lua_State *L);
}
int main();
In MyBindings.h
#include "Main.h"
class Class
{
public:
Class()
{
std::cout << "Class Constructed" << std::endl;
};
~Class()
{
std::cout << "Class Destructed" << std::endl;
};
};
In MyBindings.i (SWIG interface to generate MyBindings.cpp)
%module my
%{
#include "MyBindings.h"
%}
%include <stl.i>
%include <typemaps.i>
%include "MyBindings.h"
Result :
Class Constructed
Why is class destructor not called and how to correctly destruct classes and variables inside package.preload function?
I cannot reproduce your problem but you have other shortcomings in your code, most notably the absence of header guards. The file Main.h is not necessary and even less so in the MyBindings.h file because it doesn't make use of it. I don't know which compiler you are using but void main() is not valid C++, the standard dictates int main().
Main.cpp
#include "lua.hpp"
extern "C" int luaopen_my(lua_State *L);
int main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
luaopen_my(L);
lua_settop(L, 0);
luaL_dostring(L, "package.preload['test'] = function ()\n"
"local test = {}\n"
"local class = my.Class()\n"
"return test\n"
"end\n");
luaL_dostring(L, "require 'test'");
luaL_dostring(L, "package.preload['test'] = nil\n"
"package.loaded['test'] = nil\n");
lua_close(L);
}
MyBindings.h
#pragma once
#include <iostream>
class Class
{
public:
Class()
{
std::cout << "Class Constructed" << std::endl;
};
~Class()
{
std::cout << "Class Destructed" << std::endl;
};
};
MyBindings.i
%module my
%{
#include "MyBindings.h"
%}
%include "MyBindings.h"
Example invocation:
$ swig -c++ -lua MyBindings.i
$ clang++ -Wall -Wextra -Wpedantic -I /usr/include/lua5.2 -fPIC -shared MyBindings_wrap.cxx -o my.so -llua5.2
$ clang++ -Wall -Wextra -Wpedantic -I /usr/include/lua5.2 -L . Main.cpp -l:my.so -llua5.2
$ LD_LIBRARY_PATH=. ./a.out
Class Constructed
Class Destructed
Also you should note that Lua is a garbage collected language, i.e. destructors will run when the garbage collector thinks it is necessary. You can run the garbage collector manually using lua_gc in C or using collectgarbage in Lua but I strongly advise against running the garbage collector manually as this usually impacts performance negatively (even though you ran it manually hoping to increase performance). It only pays off to use the garbage collector manually when you are running in an environment with very limited memory and you have just pruned a table or something like that.
Anyway, I have prepared an example in Lua for you using the my.so module compiled above.
local my = require("my")
local x = my.Class()
print("Info: Deleting x")
x = nil
print("Info: Collecting garbage")
collectgarbage()
print("Info: Done :-)")
$ lua5.2 test.lua
Class Constructed
Info: Deleting x
Info: Collecting garbage
Class Destructed
Info: Done :-)
You can always call the d'tor explicitly byt obj.~class().
If you are using external classes in Lua wrapper, I'm not sire they can follow the correct nested d'tor paradigm which exists in C++.

share data pointer between c and lua module compiled with SWIG

I need to provide data structure pointer in my main program, where I have Lua state defined, to the dynamically loaded Lua module created by wrapping a c++ code using SWIG.
This is my code example:
in SimpleStruct.h:
#pragma once
struct SimpleStruct
{
int a;
double b;
};
in exmaple.h (this one is compiled with SWIG) to Lua library:
#pragma once
#include "SimpleStruct.h"
#include <iostream>
class TestClass
{
public:
TestClass()
{
std::cout<<"TestClass created"<<std::endl;
}
~TestClass() {}
void ReadSimpleStruct(void * tmp)
{
std::cout<<"reading pointer: "<<std::endl;
SimpleStruct * pp = reinterpret_cast< SimpleStruct * >(tmp);
std::cout<<"Simple Struct: " << pp->a << " " << pp->b << std::endl;
}
};
in example.cpp only:
#include "example.h"
and this is my main program (LuaTest.cpp):
extern "C"
{
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <iostream>
#include "SimpleStruct.h"
int main(int argc, char ** argv)
{
lua_State * L = luaL_newstate();
luaL_openlibs(L);
SimpleStruct * ss = new SimpleStruct();
ss->a = 1;
ss->b = 2;
lua_pushlightuserdata(L,ss);
lua_setglobal( L, "myptr");
int s = luaL_dostring(L, "require('example')");
s = luaL_dostring(L, "mc = example.TestClass()");
s = luaL_dostring(L, "mc:ReadSimpleStruct(myptr)");
if(s)
{
printf("Error: %s \n", lua_tostring(L, -1));
lua_pop(L, 1);
}
lua_close(L);
std::cout<<"done"<<std::endl;
return 0;
}
example.i (copied from Lua examples in SWIG):
/* File : example.i */
%module example
%{
#include "example.h"
%}
/* Let's just grab the original header file here */
%include "example.h"
and I compile everything as follows:
swig -c++ -lua example.i
g++ -c -fpic example.cpp example_wrap.cxx -I/usr/local/include -I/usr/include/lua5.2/
g++ -shared example.o example_wrap.o -o example.so
g++ LuaTest.cpp -o luatest -llua5.2 -I/usr/include/lua5.2/ -Wall
on Ubuntu 16.04 (and on osx, with different paths and the same result).
In the last line of Lua script I've got segmentation fault (when I try to access pp->a in "mc:ReadSimpleStruct(myptr)").
So my question is: how can I provide a pointer to c++ object to the loaded Lua library using Lua light userdata?
In general: I have in my main program a class with game parameters and objects, and I would like to provide a pointer to that class to other loaded Lua libraries compiled with a SWIG.
With use of a debugger (or just printing a little extra inside TestClass::ReadSimpleStruct) we can see at least the superficial cause of the segfault quite quickly. The value of the tmp argument to your function is 0x20 on my test setup. That's clearly not right, but understanding why and how to fix it takes a little more investigation.
As a starting point I added one more call to luaL_dostring(L, "print(myptr)") and used a debugger to check that the global variable was indead working as intended. For good measure I added some assert statements after each call to luaL_dostring, because you're actually only checking the return value of the last one, although here that didn't really make any difference.
Having not exactly written much Lua in my life I looked a the documentation for 'Light userdata', which I saw you were using but didn't know what it was. It sounds ideal:
A light userdatum is a value that represents a C pointer (that is, a void * value)
The problem is though that if we inspect the generated example_wrap.cxx file we can see that SWIG is actually trying to be more clever than that and, if we trace the code for arg2 before the generated call to (arg1)->ReadSimpleStruct(arg2) we can see that it's calling SWIG_ConvertPtr (which eventually calls SWIG_Lua_ConvertPtr), which then does:
lua_touserdata(L, index);
//... Some typing stuff from the macro
*ptr=usr->ptr; // BOOM!
I.e. what you're doing is not what SWIG expects to see for void *, SWIG is expecting to manage them all through its typing system as return values from other functions or SWIG managed globals. (I'm slightly surprised that SWIG let this get as far as a segfault without raising an error, but I think it's because void* is being special cased somewhat)
This old question served as quite a nice example to confirm my understanding of lua_pushlightuserdata. Basically we will need to write our own typemap to make this function argument get handled the way you're trying to use it (if you really do want to not let SWIG manage this?). What we want to do is very simple though. The usage case here is also substantially similar to the example I linked, except that the variable we're after when we call lua_touserdata is a function argument. That means it's at a positive offset into the stack, not a negative one. SWIG in fact can tell us what the offset inside our typemape with the $input substitution, so our typemap doesn't only work for the 1st argument to a member function.
So our typemap, which does this for any function argument void * tmp inside our modified example.i file becomes:
%module example
%{
#include "example.h"
%}
%typemap(in) void * tmp %{
$1 = lua_touserdata(L, $input);
%}
%include "example.h"
And that then compiles and runs with:
swig -c++ -lua example.i
g++ -fPIC example_wrap.cxx -I/usr/local/include -I/usr/include/lua5.2/ -shared -o example.so && g++ -Wall -Wextra LuaTest.cpp -o luatest -llua5.2 -I/usr/include/lua5.2/
./luatest
TestClass created
userdata: 0x11d0730
reading pointer: 0x11d0730
Simple Struct: 1 2
done

How do you load a custom module into Lua?

This has been driving me nuts for a long time now. I have followed every tutorial I could find on the internet (here are couple examples[ [1], [2] of the maybe half dozen good ones found via Google search), and still no clear explanation. Although it seems it must be something fairly simple as that lack of a documented explanation implies that it's something most people would take for granted.
How do I load a custom module into Lua?
On the advice of questions like this one, I have written a module that builds a shared library with the expectation that I would be able to load it through a require call. However, when I do that I get undefined symbol errors, despite those exact symbols appearing in the list from the command nm -g mylib.so.
Those two tutorials I linked before aim to create executables that look wrappers of the *.lua file. That is, the built *.exe file should be called to run the Lua program with the custom module.
I understand that these types questions are asked here fairly frequently (as noted in this answer), but I am still at a loss. I tried some of the binding packages (Luabind and OOLua), but those didn't work out great (e.g. my earlier question--which I did ultimately figure out, sort of).
I have implemented a class in C++
I have wrapped the constructors, destructors, and functions with thunks
I have built it errorless-ly as a shared library
Yet no matter what I get undefined symbol: ... errors when I try to load it as mod = require('mylib.so'). How do I do this?
Working Example of a Library of Functions
For the record, just registering a basic function works fine. The below code, when built as libluatest.so, can be run in Lua using the commands:
> require('libluatest')
> greet()
hello world!
libluatest.cpp
extern "C"
{
#include <lualib.h>
#include <lauxlib.h>
#include <lua.h>
}
#include <iostream>
static int greet(lua_State *L)
{
std::cout << "hello world!" << std::endl;
return 0;
}
static const luaL_reg funcs[] =
{
{ "greet", greet},
{ NULL, NULL }
};
extern "C" int luaopen_libluatest(lua_State* L)
{
luaL_register(L, "libluatest", funcs);
return 0;
}
Failing Example of a Class
This is what I am stuck on currently. It doesn't seem to want to work.
myObj.h
#include <string>
class MyObj
{
private:
std::string name_;
public:
MyObj();
~MyObj();
void rename(std::string name);
};
myObj.cpp
extern "C"
{
#include <lualib.h>
#include <lauxlib.h>
#include <lua.h>
}
#include <iostream>
#include "myObj.h"
void MyObj::rename(std::string name)
{
name_ = name;
std::cout << "New name: " << name_ << std::endl;
}
extern "C"
{
// Lua "constructor"
static int lmyobj_new(lua_State* L)
{
MyObj ** udata = (MyObj **)lua_newuserdata(L, sizeof(MyObj));
*udata = new MyObj();
luaL_getmetatable(L, "MyObj");
lua_setmetatable(L, -1);
return 1;
}
// Function to check the type of an argument
MyObj * lcheck_myobj(lua_State* L, int n)
{
return *(MyObj**)luaL_checkudata(L, n, "MyObj");
}
// Lua "destructor": Free instance for garbage collection
static int lmyobj_delete(lua_State* L)
{
MyObj * obj = lcheck_myobj(L, 1);
delete obj;
return 0;
}
static int lrename(lua_State* L)
{
MyObj * obj = lcheck_myobj(L, 1);
std::string new_name = luaL_checkstring(L, 2);
obj->rename(new_name);
return 0;
}
int luaopen_libmyObj(lua_State* L)
{
luaL_Reg funcs[] =
{
{ "new", lmyobj_new }, // Constructor
{ "__gc", lmyobj_delete }, // Destructor
{ "rename", lrename }, // Setter function
{ NULL, NULL } // Terminating flag
};
luaL_register(L, "MyObj", funcs);
return 0;
}
}
Compiled into libmyObj.so using a simple CMake build with C++11 standard flags on.
Error
> require('libmyObj')
error loading module 'libmyObj' from file './libmyObj.so':
./libmyObj.so: undefined symbol: _ZN5MyObjC1Ev stack traceback: [C]:
? [C]: in function 'require' stdin:1: in main chunk [C]: ?
I am dealing with Lua 5.1 on Ubuntu 14.04.
I am wondering if it has something to do with the mix of C and C++...
It seems that you do not implement:
MyObj() ; ~MyObj();
and be careful with luaopen_* function, since module name is myObj, function name should be luaopen_libmyObj.

How can I implement a C++ class in Python, to be called by C++?

I have a class interface written in C++. I have a few classes that implement this interface also written in C++. These are called in the context of a larger C++ program, which essentially implements "main". I want to be able to write implementations of this interface in Python, and allow them to be used in the context of the larger C++ program, as if they had been just written in C++.
There's been a lot written about interfacing python and C++ but I cannot quite figure out how to do what I want. The closest I can find is here: http://www.cs.brown.edu/~jwicks/boost/libs/python/doc/tutorial/doc/html/python/exposing.html#python.class_virtual_functions, but this isn't quite right.
To be more concrete, suppose I have an existing C++ interface defined something like:
// myif.h
class myif {
public:
virtual float myfunc(float a);
};
What I want to be able to do is something like:
// mycl.py
... some magic python stuff ...
class MyCl(myif):
def myfunc(a):
return a*2
Then, back in my C++ code, I want to be able to say something like:
// mymain.cc
void main(...) {
... some magic c++ stuff ...
myif c = MyCl(); // get the python class
cout << c.myfunc(5) << endl; // should print 10
}
I hope this is sufficiently clear ;)
There's two parts to this answer. First you need to expose your interface in Python in a way which allows Python implementations to override parts of it at will. Then you need to show your C++ program (in main how to call Python.
Exposing the existing interface to Python:
The first part is pretty easy to do with SWIG. I modified your example scenario slightly to fix a few issues and added an extra function for testing:
// myif.h
class myif {
public:
virtual float myfunc(float a) = 0;
};
inline void runCode(myif *inst) {
std::cout << inst->myfunc(5) << std::endl;
}
For now I'll look at the problem without embedding Python in your application, i.e. you start excetion in Python, not in int main() in C++. It's fairly straightforward to add that later though.
First up is getting cross-language polymorphism working:
%module(directors="1") module
// We need to include myif.h in the SWIG generated C++ file
%{
#include <iostream>
#include "myif.h"
%}
// Enable cross-language polymorphism in the SWIG wrapper.
// It's pretty slow so not enable by default
%feature("director") myif;
// Tell swig to wrap everything in myif.h
%include "myif.h"
To do that we've enabled SWIG's director feature globally and specifically for our interface. The rest of it is pretty standard SWIG though.
I wrote a test Python implementation:
import module
class MyCl(module.myif):
def __init__(self):
module.myif.__init__(self)
def myfunc(self,a):
return a*2.0
cl = MyCl()
print cl.myfunc(100.0)
module.runCode(cl)
With that I was then able to compile and run this:
swig -python -c++ -Wall myif.i
g++ -Wall -Wextra -shared -o _module.so myif_wrap.cxx -I/usr/include/python2.7 -lpython2.7
python mycl.py
200.0
10
Exactly what you'd hope to see from that test.
Embedding the Python in the application:
Next up we need to implement a real version of your mymain.cc. I've put together a sketch of what it might look like:
#include <iostream>
#include "myif.h"
#include <Python.h>
int main()
{
Py_Initialize();
const double input = 5.0;
PyObject *main = PyImport_AddModule("__main__");
PyObject *dict = PyModule_GetDict(main);
PySys_SetPath(".");
PyObject *module = PyImport_Import(PyString_FromString("mycl"));
PyModule_AddObject(main, "mycl", module);
PyObject *instance = PyRun_String("mycl.MyCl()", Py_eval_input, dict, dict);
PyObject *result = PyObject_CallMethod(instance, "myfunc", (char *)"(O)" ,PyFloat_FromDouble(input));
PyObject *error = PyErr_Occurred();
if (error) {
std::cerr << "Error occured in PyRun_String" << std::endl;
PyErr_Print();
}
double ret = PyFloat_AsDouble(result);
std::cout << ret << std::endl;
Py_Finalize();
return 0;
}
It's basically just standard embedding Python in another application. It works and gives exactly what you'd hope to see also:
g++ -Wall -Wextra -I/usr/include/python2.7 main.cc -o main -lpython2.7
./main
200.0
10
10
The final piece of the puzzle is being able to convert the PyObject* that you get from creating the instance in Python into a myif *. SWIG again makes this reasonably straightforward.
First we need to ask SWIG to expose its runtime in a headerfile for us. We do this with an extra call to SWIG:
swig -Wall -c++ -python -external-runtime runtime.h
Next we need to re-compile our SWIG module, explicitly giving the table of types SWIG knows about a name so we can look it up from within our main.cc. We recompile the .so using:
g++ -DSWIG_TYPE_TABLE=myif -Wall -Wextra -shared -o _module.so myif_wrap.cxx -I/usr/include/python2.7 -lpython2.7
Then we add a helper function for converting the PyObject* to myif* in our main.cc:
#include "runtime.h"
// runtime.h was generated by SWIG for us with the second call we made
myif *python2interface(PyObject *obj) {
void *argp1 = 0;
swig_type_info * pTypeInfo = SWIG_TypeQuery("myif *");
const int res = SWIG_ConvertPtr(obj, &argp1,pTypeInfo, 0);
if (!SWIG_IsOK(res)) {
abort();
}
return reinterpret_cast<myif*>(argp1);
}
Now this is in place we can use it from within main():
int main()
{
Py_Initialize();
const double input = 5.5;
PySys_SetPath(".");
PyObject *module = PyImport_ImportModule("mycl");
PyObject *cls = PyObject_GetAttrString(module, "MyCl");
PyObject *instance = PyObject_CallFunctionObjArgs(cls, NULL);
myif *inst = python2interface(instance);
std::cout << inst->myfunc(input) << std::endl;
Py_XDECREF(instance);
Py_XDECREF(cls);
Py_Finalize();
return 0;
}
Finally we have to compile main.cc with -DSWIG_TYPE_TABLE=myif and this gives:
./main
11
Minimal example; note that it is complicated by the fact that Base is not pure virtual. There we go:
baz.cpp:
#include<string>
#include<boost/python.hpp>
using std::string;
namespace py=boost::python;
struct Base{
virtual string foo() const { return "Base.foo"; }
// fooBase is non-virtual, calling it from anywhere (c++ or python)
// will go through c++ dispatch
string fooBase() const { return foo(); }
};
struct BaseWrapper: Base, py::wrapper<Base>{
string foo() const{
// if Base were abstract (non-instantiable in python), then
// there would be only this->get_override("foo")() here
//
// if called on a class which overrides foo in python
if(this->get_override("foo")) return this->get_override("foo")();
// no override in python; happens if Base(Wrapper) is instantiated directly
else return Base::foo();
}
};
BOOST_PYTHON_MODULE(baz){
py::class_<BaseWrapper,boost::noncopyable>("Base")
.def("foo",&Base::foo)
.def("fooBase",&Base::fooBase)
;
}
bar.py
import sys
sys.path.append('.')
import baz
class PyDerived(baz.Base):
def foo(self): return 'PyDerived.foo'
base=baz.Base()
der=PyDerived()
print base.foo(), base.fooBase()
print der.foo(), der.fooBase()
Makefile
default:
g++ -shared -fPIC -o baz.so baz.cpp -lboost_python `pkg-config python --cflags`
And the result is:
Base.foo Base.foo
PyDerived.foo PyDerived.foo
where you can see how fooBase() (the non-virtual c++ function) calls virtual foo(), which resolves to the override regardless whether in c++ or python. You could derive a class from Base in c++ and it would work just the same.
EDIT (extracting c++ object):
PyObject* obj; // given
py::object pyObj(obj); // wrap as boost::python object (cheap)
py::extract<Base> ex(pyObj);
if(ex.check()){ // types are compatible
Base& b=ex(); // get the wrapped object
// ...
} else {
// error
}
// shorter, thrwos when conversion not possible
Base &b=py::extract<Base>(py::object(obj))();
Construct py::object from PyObject* and use py::extract to query whether the python object matches what you are trying to extract: PyObject* obj; py::extract<Base> extractor(py::object(obj)); if(!extractor.check()) /* error */; Base& b=extractor();
Quoting http://wiki.python.org/moin/boost.python/Inheritance
"Boost.Python also allows us to represent C++ inheritance relationships so that wrapped derived classes may be passed where values, pointers, or references to a base class are expected as arguments."
There are examples of virtual functions so that solves the first part (the one with class MyCl(myif))
For specific examples doing this, http://wiki.python.org/moin/boost.python/OverridableVirtualFunctions
For the line myif c = MyCl(); you need to expose your python (module) to C++. There are examples here http://wiki.python.org/moin/boost.python/EmbeddingPython
Based upon the (very helpful) answer by Eudoxos I've taken his code and extended it such that there is now an embedded interpreter, with a built-in module.
This answer is the Boost.Python equivalent of my SWIG based answer.
The headerfile myif.h:
class myif {
public:
virtual float myfunc(float a) const { return 0; }
virtual ~myif() {}
};
Is basically as in the question, but with a default implementation of myfunc and a virtual destructor.
For the Python implementation, MyCl.py I have basically the same as the question:
import myif
class MyCl(myif.myif):
def myfunc(self,a):
return a*2.0
This then leaves mymain.cc, most of which is based upon the answer from Eudoxos:
#include <boost/python.hpp>
#include <iostream>
#include "myif.h"
using namespace boost::python;
// This is basically Eudoxos's answer:
struct MyIfWrapper: myif, wrapper<myif>{
float myfunc(float a) const {
if(this->get_override("myfunc"))
return this->get_override("myfunc")(a);
else
return myif::myfunc(a);
}
};
BOOST_PYTHON_MODULE(myif){
class_<MyIfWrapper,boost::noncopyable>("myif")
.def("myfunc",&myif::myfunc)
;
}
// End answer by Eudoxos
int main( int argc, char ** argv ) {
try {
// Tell python that "myif" is a built-in module
PyImport_AppendInittab("myif", initmyif);
// Set up embedded Python interpreter:
Py_Initialize();
object main_module = import("__main__");
object main_namespace = main_module.attr("__dict__");
PySys_SetPath(".");
main_namespace["mycl"] = import("mycl");
// Create the Python object with an eval()
object obj = eval("mycl.MyCl()", main_namespace);
// Find the base C++ type for the Python object (from Eudoxos)
const myif &b=extract<myif>(obj)();
std::cout << b.myfunc(5) << std::endl;
} catch( error_already_set ) {
PyErr_Print();
}
}
The key part that I've added here, above and beyond the "how do I embed Python using Boost.Python?" and "how do I extend Python using Boost.python?" (which was answered by Eudoxos) is the answer to the question "How do I do both at once in the same program?". The solution to this lies with the PyImport_AppendInittab call, which takes the initialisation function that would normally be called when the module is loaded and registers it as a built-in module. Thus when mycl.py says import myif it ends up importing the built-in Boost.Python module.
Take a look at Boost Python, that is the most versatile and powerful tool to bridge between C++ and Python.
http://www.boost.org/doc/libs/1_48_0/libs/python/doc/
There's no real way to interface C++ code directly with Python.
SWIG does handle this, but it builds its own wrapper.
One alternative I prefer over SWIG is ctypes, but to use this you need to create a C wrapper.
For the example:
// myif.h
class myif {
public:
virtual float myfunc(float a);
};
Build a C wrapper like so:
extern "C" __declspec(dllexport) float myif_myfunc(myif* m, float a) {
return m->myfunc(a);
}
Since you are building using C++, the extern "C" allows for C linkage so you can call it easily from your dll, and __declspec(dllexport) allows the function to be called from the dll.
In Python:
from ctypes import *
from os.path import dirname
dlldir = dirname(__file__) # this strips it to the directory only
dlldir.replace( '\\', '\\\\' ) # Replaces \ with \\ in dlldir
lib = cdll.LoadLibrary(dlldir+'\\myif.dll') # Loads from the full path to your module.
# Just an alias for the void pointer for your class
c_myif = c_void_p
# This tells Python how to interpret the return type and arguments
lib.myif_myfunc.argtypes = [ c_myif, c_float ]
lib.myif_myfunc.restype = c_float
class MyCl(myif):
def __init__:
# Assume you wrapped a constructor for myif in C
self.obj = lib.myif_newmyif(None)
def myfunc(a):
return lib.myif_myfunc(self.obj, a)
While SWIG does all this for you, there's little room for you to modify things as you please without getting frustrated at all the changes you have to redo when you regenerate the SWIG wrapper.
One issue with ctypes is that it doesn't handle STL structures, since it's made for C. SWIG does handle this for you, but you may be able to wrap it yourself in the C. It's up to you.
Here's the Python doc for ctypes:
http://docs.python.org/library/ctypes.html
Also, the built dll should be in the same folder as your Python interface (why wouldn't it be?).
I am curious though, why would you want to call Python from inside C++ instead of calling the C++ implementation directly?

How to use C++ in Go

In the new Go language, how do I call C++ code? In other words, how can I wrap my C++ classes and use them in Go?
Update: I've succeeded in linking a small test C++ class with Go
If you wrap you C++ code with a C interface you should be able to call your library with cgo (see the example of gmp in $GOROOT/misc/cgo/gmp).
I'm not sure if the idea of a class in C++ is really expressible in Go, as it doesn't have inheritance.
Here's an example:
I have a C++ class defined as:
// foo.hpp
class cxxFoo {
public:
int a;
cxxFoo(int _a):a(_a){};
~cxxFoo(){};
void Bar();
};
// foo.cpp
#include <iostream>
#include "foo.hpp"
void
cxxFoo::Bar(void){
std::cout<<this->a<<std::endl;
}
which I want to use in Go. I'll use the C interface
// foo.h
#ifdef __cplusplus
extern "C" {
#endif
typedef void* Foo;
Foo FooInit(void);
void FooFree(Foo);
void FooBar(Foo);
#ifdef __cplusplus
}
#endif
(I use a void* instead of a C struct so the compiler knows the size of Foo)
The implementation is:
//cfoo.cpp
#include "foo.hpp"
#include "foo.h"
Foo FooInit()
{
cxxFoo * ret = new cxxFoo(1);
return (void*)ret;
}
void FooFree(Foo f)
{
cxxFoo * foo = (cxxFoo*)f;
delete foo;
}
void FooBar(Foo f)
{
cxxFoo * foo = (cxxFoo*)f;
foo->Bar();
}
with all that done, the Go file is:
// foo.go
package foo
// #include "foo.h"
import "C"
import "unsafe"
type GoFoo struct {
foo C.Foo;
}
func New()(GoFoo){
var ret GoFoo;
ret.foo = C.FooInit();
return ret;
}
func (f GoFoo)Free(){
C.FooFree(unsafe.Pointer(f.foo));
}
func (f GoFoo)Bar(){
C.FooBar(unsafe.Pointer(f.foo));
}
The makefile I used to compile this was:
// makefile
TARG=foo
CGOFILES=foo.go
include $(GOROOT)/src/Make.$(GOARCH)
include $(GOROOT)/src/Make.pkg
foo.o:foo.cpp
g++ $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $# -c $(CGO_CFLAGS) $<
cfoo.o:cfoo.cpp
g++ $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $# -c $(CGO_CFLAGS) $<
CGO_LDFLAGS+=-lstdc++
$(elem)_foo.so: foo.cgo4.o foo.o cfoo.o
gcc $(_CGO_CFLAGS_$(GOARCH)) $(_CGO_LDFLAGS_$(GOOS)) -o $# $^ $(CGO_LDFLAGS)
Try testing it with:
// foo_test.go
package foo
import "testing"
func TestFoo(t *testing.T){
foo := New();
foo.Bar();
foo.Free();
}
You'll need to install the shared library with make install, then run make test. Expected output is:
gotest
rm -f _test/foo.a _gotest_.6
6g -o _gotest_.6 foo.cgo1.go foo.cgo2.go foo_test.go
rm -f _test/foo.a
gopack grc _test/foo.a _gotest_.6 foo.cgo3.6
1
PASS
Seems that currently SWIG is best solution for this:
https://www.swig.org/Doc4.0/Go.html
It supports inheritance and even allows to subclass C++ class with Go struct so when overridden methods are called in C++ code, Go code is fired.
Section about C++ in Go FAQ is updated and now mentions SWIG and no longer says "because Go is garbage-collected it will be unwise to do so, at least naively".
As of go1.2+, cgo automatically incorporates and compiles C++ code:
http://golang.org/doc/go1.2#cgo_and_cpp
You can't quite yet from what I read in the FAQ:
Do Go programs link with C/C++ programs?
There are two Go compiler implementations, gc (the 6g program and friends) and gccgo. Gc uses a different calling convention and linker and can therefore only be linked with C programs using the same convention. There is such a C compiler but no C++ compiler. Gccgo is a GCC front-end that can, with care, be linked with GCC-compiled C or C++ programs.
The cgo program provides the mechanism for a “foreign function interface” to allow safe calling of C libraries from Go code. SWIG extends this capability to C++ libraries.
I've created the following example based on Scott Wales' answer. I've tested it in macOS High Sierra 10.13.3 running go version go1.10 darwin/amd64.
(1) Code for library.hpp, the C++ API we aim to call.
#pragma once
class Foo {
public:
Foo(int value);
~Foo();
int value() const;
private:
int m_value;
};
(2) Code for library.cpp, the C++ implementation.
#include "library.hpp"
#include <iostream>
Foo::Foo(int value) : m_value(value) {
std::cout << "[c++] Foo::Foo(" << m_value << ")" << std::endl;
}
Foo::~Foo() { std::cout << "[c++] Foo::~Foo(" << m_value << ")" << std::endl; }
int Foo::value() const {
std::cout << "[c++] Foo::value() is " << m_value << std::endl;
return m_value;
}
(3) Code for library-bridge.h the bridge needed to expose a C API implemented in C++ so that go can use it.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void* LIB_NewFoo(int value);
void LIB_DestroyFoo(void* foo);
int LIB_FooValue(void* foo);
#ifdef __cplusplus
} // extern "C"
#endif
(4) Code for library-bridge.cpp, the implementation of the bridge.
#include <iostream>
#include "library-bridge.h"
#include "library.hpp"
void* LIB_NewFoo(int value) {
std::cout << "[c++ bridge] LIB_NewFoo(" << value << ")" << std::endl;
auto foo = new Foo(value);
std::cout << "[c++ bridge] LIB_NewFoo(" << value << ") will return pointer "
<< foo << std::endl;
return foo;
}
// Utility function local to the bridge's implementation
Foo* AsFoo(void* foo) { return reinterpret_cast<Foo*>(foo); }
void LIB_DestroyFoo(void* foo) {
std::cout << "[c++ bridge] LIB_DestroyFoo(" << foo << ")" << std::endl;
AsFoo(foo)->~Foo();
}
int LIB_FooValue(void* foo) {
std::cout << "[c++ bridge] LIB_FooValue(" << foo << ")" << std::endl;
return AsFoo(foo)->value();
}
(5) Finally, library.go, the go program calling the C++ API.
package main
// #cgo LDFLAGS: -L. -llibrary
// #include "library-bridge.h"
import "C"
import "unsafe"
import "fmt"
type Foo struct {
ptr unsafe.Pointer
}
func NewFoo(value int) Foo {
var foo Foo
foo.ptr = C.LIB_NewFoo(C.int(value))
return foo
}
func (foo Foo) Free() {
C.LIB_DestroyFoo(foo.ptr)
}
func (foo Foo) value() int {
return int(C.LIB_FooValue(foo.ptr))
}
func main() {
foo := NewFoo(42)
defer foo.Free() // The Go analog to C++'s RAII
fmt.Println("[go]", foo.value())
}
Using the following Makefile
liblibrary.so: library.cpp library-bridge.cpp
clang++ -o liblibrary.so library.cpp library-bridge.cpp \
-std=c++17 -O3 -Wall -Wextra -fPIC -shared
I can run the example program as follows:
$ make
clang++ -o liblibrary.so library.cpp library-bridge.cpp \
-std=c++17 -O3 -Wall -Wextra -fPIC -shared
$ go run library.go
[c++ bridge] LIB_NewFoo(42)
[c++] Foo::Foo(42)
[c++ bridge] LIB_NewFoo(42) will return pointer 0x42002e0
[c++ bridge] LIB_FooValue(0x42002e0)
[c++] Foo::value() is 42
[go] 42
[c++ bridge] LIB_DestroyFoo(0x42002e0)
[c++] Foo::~Foo(42)
Important
The comments above import "C" in the go program are NOT OPTIONAL. You must put them exactly as shown so that cgo knows which header and library to load, in this case:
// #cgo LDFLAGS: -L. -llibrary
// #include "library-bridge.h"
import "C"
Link to GitHub repo with the full example.
Looks it's one of the early asked question about Golang . And same time answers to never update . During these three to four years , too many new libraries and blog post has been out . Below are the few links what I felt useful .
SWIG and Go
Calling C++ Code From Go With SWIG
On comparing languages, C++ and Go
GoForCPPProgrammers
There's talk about interoperability between C and Go when using the gcc Go compiler, gccgo. There are limitations both to the interoperability and the implemented feature set of Go when using gccgo, however (e.g., limited goroutines, no garbage collection).
You're walking on uncharted territory here. Here is the Go example for calling C code, perhaps you can do something like that after reading up on C++ name mangling and calling conventions, and lots of trial and error.
If you still feel like trying it, good luck.
You might need to add -lc++ to the LDFlags for Golang/CGo to recognize the need for the standard library.
The problem here is that a compliant implementation does not need to put your classes in a compile .cpp file. If the compiler can optimize out the existence of a class, so long as the program behaves the same way without it, then it can be omitted from the output executable.
C has a standardized binary interface. Therefore you'll be able to know that your functions are exported. But C++ has no such standard behind it.
Funny how many broader issues this announcement has dredged up. Dan Lyke had a very entertaining and thoughtful discussion on his website, Flutterby, about developing Interprocess Standards as a way of bootstrapping new languages (and other ramifications, but that's the one that is germane here).
This can be achieved using command cgo.
In essence
'If the import of "C" is immediately preceded by a comment, that comment, called the preamble, is used as a header when compiling the C parts of the package. For example:'
source:https://golang.org/cmd/cgo/
// #include <stdio.h>
// #include <errno.h>
import "C"