[C++-sig] [Swig-user] A callback function with arguments causes error

Bruce Who bruce.who.hk at gmail.com
Tue May 15 02:25:30 CEST 2007


Hi, Monty,

Thanks for your code, but I still cannot figure out why it doesnot
work. This is all of my code, it is just the callback example of swig
with a little modification, but it just doesnot work:

// ================== example.h
#include <cstdio>
#include <iostream>

class Callback {
public:
	virtual ~Callback() { std::cout << "Callback::~Callback()" << std:: endl; }
	// virtual void run() { std::cout << "Callback::run()" << std::endl; }
	virtual void run(int* pn) { std::cout << "Callback::run()" << (*pn)
<< std::endl; }
};


class Caller {
private:
	Callback *_callback;
public:
	Caller(): _callback(0) {}
	~Caller() { delCallback(); }
	void delCallback() { delete _callback; _callback = 0; }
	void setCallback(Callback *cb) { delCallback(); _callback = cb; }
	// void call() { if (_callback) _callback->run(); }
	void call()
    {
        if (_callback)
        {
            int i = 90;
            _callback->run(&i);
        }
    }
};


// ================== example.cxx
#include "example.h"


// ================== example.i
%module(directors="1") example
%{
#include "example.h"
%}

%include "std_string.i"

%feature("director") Callback;

%include "example.h"


@rem ================== build.bat
@rem I compile my code with this bat file
set FILENAME=example

call "D:\program\Microsoft Visual Studio 8\VC\bin\vcvars32"
swig -c++ -python %FILENAME%.i

cl -c %FILENAME%_wrap.cxx -ID:\program\Python25\include\

link /subsystem:windows /LIBPATH:D:\program\Python25\libs\
%FILENAME%_wrap.obj /dll /OUT:_%FILENAME%.pyd


#===================================================
# file: runme.py
# you can test the wrapper with this script

import example

class PyCallback(example.Callback):
    def __init__(self):
        example.Callback.__init__(self)
    def run(self, i):
        print "PyCallback.run()", i

# Create an Caller instance

caller = example.Caller()

# Add a simple C++ callback (caller owns the callback, so
# we disown it first by clearing the .thisown flag).

print "Adding and calling a normal C++ callback"
print "----------------------------------------"

callback = example.Callback()
callback.thisown = 0
caller.setCallback(callback)
caller.call()
caller.delCallback();

print
print "Adding and calling a Python callback"
print "------------------------------------"

# Add a Python callback (caller owns the callback, so we
# disown it first by calling __disown__).

caller.setCallback(PyCallback().__disown__())
caller.call()
caller.delCallback()

print
print "Adding and calling another Python callback"
print "------------------------------------------"

# Lets do the same but use the weak reference this time.

callback = PyCallback().__disown__()
caller.setCallback(callback)
caller.call()
caller.delCallback()

# All done.

print
print "python exit"


After compiling all code, I run it:
E:\test>runme.py
Adding and calling a normal C++ callback
----------------------------------------
Callback::run()90
Callback::~Callback()

Adding and calling a Python callback
------------------------------------
PyCallback.run()

and then a windows message box pops up saying that there is something
wrong with python.exe.


On 5/15/07, Monty Taylor <monty at inaugust.com> wrote:
> Hi Bruce,
>
> I'm using a callback with arguments from Python using directors.
>
> I've got this:
>
> class BaseCallback {
>   public:
>   virtual ~BaseCallback() {};
>   virtual void callback(int res, NdbTransaction * trans);
>
> };
>
>
> Then from python:
>
> class PythonCallback(ndbapi.BaseCallback):
>
>   def __init__(self, recAttr):
>     self.recAttr=recAttr
>
>   def __call__(self, *args, **kw):
>     self.callback(*args,**kw)
>
>   def callback(self, ret, myTrans):
>     x=self.recAttr.get_value()
>
> Works like a charm. Are you sure everything is working right with memory
> ownership and that int *? I'd try it with just a normal int first to see
> if that's the problem, then go in and figure out how to get Python to
> allocate and pass the int* in such a way that it still exists when you
> access it in the callback... but I could be way off base there.
>
> Monty



More information about the Cplusplus-sig mailing list