Convert C++ Syntax to Objective C - c++

My background experience is C/C++/C#.
I am using a C++ library in an xcode project (to be specific the library is PJSIP). To use the library i have to wire couple of callbacks to my code like this:
SipTest.m
#include < pjsua-lib/pjsua.h >
static void on_reg_state(pjsua_acc_id acc_id)
{
// Do work
}
static void Init()
{
// pjsua_config and psjua_config_default are defined in the header file from pjsip
pjsua_config cfg;
psjua_config_default(&cfg);
cfg.cb.on_regstate = &on_reg_state;
}
I want to switch this C++ sytnax to Objective C
so I did:
+(void) on_reg_state:(pjsua_acc_id) acc_id
{
// Do work
}
+(void) Init
{
pjsua_config cfg;
psjua_config_default(&cfg);
cfg.cb.on_regstate = &on_reg_state; // ***** this is causing compile error
// I tried [CLASS NAME on_reg_state] and i get runtime error
}
I tried to search for delegate in Objective C but i could not find an a similar case where the callback is already implemented in C++ and you want to use it with Objective-C syntax.
Thanks

First of all, there's absolutely no need to convert anything at all. It is perfectly fine to call C++ libraries from Objective-C.
Secondly, whats causing the compiler error is that you're trying to stick a method in a place where there should be a function pointer. You can't make a function pointer out of an Objective-C method using the & Operator. Simply keep your on_reg_state() function and use it as you did before, that's how you do callbacks in Apple's C-based frameworks, too (which you'll need as soon as you move beyond what the high-level Objective-C APIs provide).
And thirdly, your + (void)Init method seems a bit strange. I would strongly discourage you to write a method called Init (capitalized). If you intend to write an initializer, it should be - (id)init, i.e. lowercase and returning id. And don't forget to call the designated initializer of its superclass, check its return value, assign it to self, and return it at the end of the init method (see Implementing an Initializer in Apple's documentation if you're not familiar with that). And if your method is not an initializer, use a different name, e.g. - (void)createConfig.

in this case you'd want to use selectors.
+(void) on_reg_state:(pjsua_acc_id) acc_id
{
// Do work
}
+(void) Init
{
pjsua_config cfg;
psjua_config_default(&cfg);
cfg.cb.on_regstate_selector = #selector(on_reg_state:);
cfg.cb.target = self; //Self here is the class object in your 'Init' method, which is poorly named.
//Use this like [cfg.cb.target performSelector:cfg.cb.on_regstate_selector withObject:...etc]
}

Related

How does it work and compile a C++ extension of TCL with a Macro and no main function

I have a working set of TCL script plus C++ extension but I dont know exactly how it works and how was it compiled. I am using gcc and linux Arch.
It works as follows: when we execute the test.tcl script it will pass some values to an object of a class defined into the C++ extension. Using these values the extension using a macro give some result and print some graphics.
In the test.tcl scrip I have:
#!object
use_namespace myClass
proc simulate {} {
uplevel #0 {
set running 1
for {} {$running} { } {
moveBugs
draw .world.canvas
.statusbar configure -text "t:[tstep]"
}
}
}
set toroidal 1
set nx 100
set ny 100
set mv_dist 4
setup $nx $ny $mv_dist $toroidal
addBugs 100
# size of a grid cell in pixels
set scale 5
myClass.scale 5
The object.cc looks like:
#include //some includes here
MyClass myClass;
make_model(myClass); // --> this is a macro!
The Macro "make_model(myClass)" expands as follows:
namespace myClass_ns { DEFINE_MYLIB_LIBRARY; int TCL_obj_myClass
(mylib::TCL_obj_init(myClass),TCL_obj(mylib::null_TCL_obj,
(std::string)"myClass",myClass),1); };
The Class definition is:
class MyClass:
{
public:
int tstep; //timestep - updated each time moveBugs is called
int scale; //no. pixels used to represent bugs
void setup(TCL_args args) {
int nx=args, ny=args, moveDistance=args;
bool toroidal=args;
Space::setup(nx,ny,moveDistance,toroidal);
}
The whole thing creates a cell-grid with some dots (bugs) moving from one cell to another.
My questions are:
How do the class methods and variables get the script values?
How is possible to have c++ code and compile it without a main function?
What is that macro doing there in the extension and how it works??
Thanks
Whenever a command in Tcl is run, it calls a function that implements that command. That function is written in a language like C or C++, and it is passed in the arguments (either as strings or Tcl_Obj* values). A full extension will also include a function to do the library initialisation; the function (which is external, has C linkage, and which has a name like Foo_Init if your library is foo.dll) does basic setting up tasks like registering the implementation functions as commands, and it's explicit because it takes a reference to the interpreter context that is being initialised.
The implementation functions can do pretty much anything they want, but to return a result they use one of the functions Tcl_SetResult, Tcl_SetObjResult, etc. and they have to return an int containing the relevant exception code. The usual useful ones are TCL_OK (for no exception) and TCL_ERROR (for stuff's gone wrong). This is a C API, so C++ exceptions aren't allowed.
It's possible to use C++ instance methods as command implementations, provided there's a binding function in between. In particular, the function has to get the instance pointer by casting a ClientData value (an alias for void* in reality, remember this is mostly a C API) and then invoking the method on that. It's a small amount of code.
Compiling things is just building a DLL that links against the right library (or libraries, as required). While extensions are usually recommended to link against the stub library, it's not necessary when you're just developing and testing on one machine. But if you're linking against the Tcl DLL, you'd better make sure that the code gets loaded into a tclsh that uses that DLL. Stub libraries get rid of that tight binding, providing pretty strong ABI stability, but are little more work to set up; you need to define the right C macro to turn them on and you need to do an extra API call in your initialisation function.
I assume you already know how to compile and link C++ code. I won't tell you how to do it, but there's bound to be other questions here on Stack Overflow if you need assistance.
Using the code? For an extension, it's basically just:
# Dynamically load the DLL and call the init function
load /path/to/your.dll
# Commands are all present, so use them
NewCommand 3
There are some extra steps later on to turn a DLL into a proper Tcl package, abstracting code that uses the DLL away from the fact that it is exactly that DLL and so on, but they're not something to worry about until you've got things working a lot more.

How to create a NSAutoreleasePool without Objective-C?

I have multiplatform game written in C++. In the mac version, even though I do not have any obj-c code, one of the libraries I use seems to be auto-releasing stuff, and I get memory leaks for that, since I did not create a NSAutoreleasePool.
What I want is to be able to create (and destroy) a NSAutoreleasePool without using obj-c code, so I don't need to create a .m file, and change my build scripts just for that. Is that possible? How can that be done?
OBS: Tagged C and C++, because a solution in any of those languages will do.
You can't avoid instantiating the Objective-C runtime—but apparently you've already got one of those.
If you want to interact with the runtime from C, you can us the Objective-C runtime APIs, as documented in Objective-C Runtime Programming Guide and Objective-C Runtime Reference.
The idea is something like this (untested):
#include <objc/runtime.h>
#include <objc/objc-runtime.h>
id allocAndInitAutoreleasePool() {
Class NSAutoreleasePoolClass = objc_getClass("NSAutoreleasePool");
id pool = class_createInstance(NSAutoreleasePoolClass, 0);
return objc_msgSend(pool, "init");
}
void drainAutoreleasePool(id pool) {
(void)objc_msgSend(pool, "drain");
}
If you want to call these functions from another file, of course you'll have to include objc/runtime.h there as well. Or, alternatively, you can cast the id to void* in the return from the allocAndInit function, and take a void* and cast back to id in the drain function. (You could also forward-declare struct objc_object and typedef struct objc_object *id, but I believe that's not actually guaranteed to be the right definition.)
You shouldn't have to pass -lobjc in your link command.
Needless to say, it's probably less work to just make your build scripts handle .m files.

Is the python C API entirely compatible with C++?

As I understand the relationship between C and C++, the latter is essentially an extension of the former and retains a certain degree of backwards compatibility. Is it safe to assume that the python C API can be called with C++ code?
More to the point, I notice that the official python documentation bundles C and C++ extensions together on the same page. Nowhere am I able to find a C++ API. This leads me to believe that the same API is safe to use in both languages.
Can someone confirm or deny this?
EDIT:
I think I made my question much more complicated than it needs to be. The question is this: what must I do in order to write a python module in C++? Do I just follow the same directions as listed here, substituting C code for C++? Is there a separate API?
I can confirm that the same Python C API is safe to be used in both languages, C and C++.
However, it is difficult to provide you with more detailed answer, unless you will ask more specific question. There are numerous caveats and issues you should be aware of. For example, your Python extensions are defined as C types struct, not as C++, so don't expect to have their constructor/destructor implicitly defined and called.
For example, taking the sample code from Defining New Types in the Python manual, it can be written in C++ way and you can even blend-in C++ types:
// noddy.cpp
namespace {
struct noddy_NoddyObject
{
PyObject_HEAD
// Type-specific fields go here.
std::shared_ptr<int> value; // WARNING
};
PyObject* Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
try {
Noddy *self = (Noddy *)type->tp_alloc(type, 0);
if (self) {
self->value = std::make_shared(7);
// or more complex operations that may throw
// or extract complex initialisation as Noddy_init function
return self;
}
}
catch (...) {
// do something, log, etc.
}
return 0;
}
PyTypeObject noddy_NoddyType =
{
PyObject_HEAD_INIT(NULL)
// ...
}
} // unnamed namespace
But, neither constructor nor destructor of the std::shared_ptr will be called.
So, remember to define dealloc function for your noddy_NoddyType where you will reset the value with nullptr. Why even bother with having value defined as shared_ptr, you may ask. It is useful if you use your Python extension in C++, with exceptions, to avoid type conversions and casts, to have more seamless integration inside definitions of your implementation, error handling based on exception may be easier then, etc.
And in spite of the fact that your objects of the noddy_NoddyType are managed by machinery implemented in pure C, thanks to dealloc function the value will be released according to well-known RAII rules.
Here you can find interesting example of nearly seamless integration of Python C API with the C++ language: How To catch Python stdout in c++ code
Python C API can be called within C++ code.
Python C++ extensions are written using the same C API as C extensions use, or using some 3rd party API, such as boost::python.

How to wrap an init/cleanup function in Boost python

I recently discovered the existence of boost-python and was astonished by it's apparent simplicity. I wanted to give it a try and started to wrap an existing C++ library.
While wrapping the basic library API calls is quite simple (nothing special, just regular function calls and very common parameters), I don't know how to properly wrap the initialization/cleanup functions:
As it stands, my C++ library requires the caller to first call mylib::initialize() when the program starts, and to call mylib::cleanup() before it ends (actually there is also an initializer object that takes care of that, but it is probably irrelevant).
How should I wrap this using boost python ?
Forcing a Python user to call mymodule.initialize() and mymodule.cleanup() seems not very pythonic. Is there any way to that in an automatic fashion ? Ideally, the call to initialize() would be done transparently when the module is imported and the call to cleanup() also done when the python script ends.
Is there any way to do that ? If not, what is the most elegant solution ?
Thank you.
You could try to do a guard object and assign it to a hidden attribute of your module.
struct MyLibGuard
{
MyLibGuard() { myLib::initialize();}
~MyLibGuard() { myLib::cleanup();}
};
using namespace boost::python;
BOOST_PYTHON_MODULE(arch_lib)
{
boost::shared_ptr<MyLibGuard> libGuard = new MyLibGuard();
class_<MyLibGuard, boost::shared_ptr<MyLibGuard>, boost::noncopyable>("MyLibGuard", no_init);
scope().attr("__libguard") = libGuard;
}

Embedding Lua in C++: Accessing C++ created through Lua, back in C++ (or returning results back from Lua to C++)

The title probably sounds a bit recursive - but this is what I am trying to do:
I have C++ classes Foo and Foobar;
I am using tolua++ to export them to Lua
In Lua:
function wanna_be_starting_something()
foo = Foo:new()
fb = Foobar:new()
-- do something
foo.setResult(42) -- <- I want to store something back at the C++ end
end
In C++
int main(int argc, char argv[])
{
MyResult res;
LuaEngine * engine = new LuaEngine();
engine->run('wbs-something.lua');
// I now want to be able to access the stored result, in variable res
};
So my question is this: how do I pass data from a C++ object that is being manipulated by Lua, back into a C++ program?
To understand how to exchange data back and forth, you should learn about the Lua stack that is the structure Lua uses to communicate with the host program. I guess tolua++ takes care of this for the classes/methods you exported.
Here there is a good start: http://www.lua.org/pil/24.html is for Lua 5.0 but there are indications on how to make it work with 5.1 (which I assume is the Lua version you're using).
If you don't want to dig into all the details, you can always resort to create an ad-hoc C++ method that sets values into a global object. Not the cleanest way, IMHO, but could work.
I don't know tolua++, but both luabind and luabridge support what you need:
* option 1 is just to have the lua code do return whatever and you'll get the that in C++. This require that you'll have a template based version of run(), which returns a value.
* option 2 is to use the lua engine to define a function and then use the engine's call method with the function name and parameters. There are several implementations of LuaEngine which support such a call:
LuaEngine * engine = new LuaEngine();
engine->run("function a(v) return v . 'a'; end ");
valua = engine->call("a", argument);

Categories