articleC/C++ calls and callbacks

Most existing examples on how to do external calls contain a lot of English explanation which can distract people, like myself, who learn by example. This is intended to be a compilable, terse example of how to call in and out of C/C++.


This is a C example:

class
	APPLICATION
 
create
	make
 
feature -- Initialization
 
	make is
			-- Run application.
		do
			create callback
			c_set_routine (callback.routine)
			c_set_object ($callback)
			c_do_callback
		end
 
	callback: CALLABLE
 
feature{NONE}
	c_set_routine (routine: POINTER) is
		external
			"C inline use %"application.h%""
		alias
			"c_set_routine ($routine);"
		end
 
	c_set_object (obj: POINTER) is
		external
			"C inline use %"application.h%""
		alias
			"c_set_object ($obj);"
		end
 
	c_do_callback is
		external
			"C inline use %"application.h%""
		alias
			"c_do_callback();"
		end
end -- class APPLICATION

class
	CALLABLE
 
feature
	inside is
		local
			current_addr: POINTER
		do
			current_addr := $Current
			io.put_string ("We're inside at address: " + current_addr.to_integer_32.out)
			io.put_new_line
		end
 
	routine: POINTER is
		do
			result := $inside
		end
end

application.h:

#include "eif_eiffel.h"
 
EIF_OBJECT obj = NULL;
EIF_POINTER routine;
 
void c_set_routine (EIF_POINTER routine_a)
{
	routine = routine_a;
}
 
void c_set_object (EIF_REFERENCE obj_a)
{
	if(obj != NULL)
	{
		eif_wean (obj);
	}
	obj = eif_protect (obj_a);
}
 
void c_do_callback ()
{
	((void (*) (EIF_REFERENCE)) routine) (eif_access (obj));
}

This is a similar C++ example:

class
	APPLICATION
 
create
	make
 
feature -- Initialization
 
	make is
		do
			create call
			cpp_obj := c_new
			c_set_routine (cpp_obj, call.routine)
			c_set_object (cpp_obj, $call)
			c_do_callback (cpp_obj)
		end
 
	cpp_obj: POINTER
	call: CALLABLE
 
feature {NONE}
	c_new: POINTER is
		external
			"C++ inline use %"application.h%""
		alias
			"[
				return new test_class;
			]"
		end
 
	c_set_routine (obj: POINTER routine: POINTER) is
		external
			"C++ inline use %"application.h%""
		alias
			"((test_class *) ($obj))->c_set_routine ($routine);"
		end
 
	c_set_object (obj: POINTER e_obj: POINTER) is
		external
			"C++ inline use %"application.h%""
		alias
			"((test_class *) ($obj))->c_set_object ((EIF_REFERENCE)$e_obj);"
		end
 
	c_do_callback (obj: POINTER) is
		external
			"C++ inline use %"application.h%""
		alias
			"((test_class *) ($obj))->c_do_callback();"
		end
end

class
	CALLABLE
 
feature
	inside is
		local
			current_addr: POINTER
		do
			current_addr := $Current
			io.put_string ("We're inside at address: " + current_addr.to_integer_32.out)
			io.put_new_line
		end
 
	routine: POINTER is
		do
			result := $inside
		end
end

application.h:

#include "eif_eiffel.h"
 
class test_class
{
public:
	test_class();
	~test_class();
	EIF_OBJECT obj;
	EIF_POINTER routine;
	void c_set_object (EIF_REFERENCE obj_a);
	void c_set_routine (EIF_POINTER routine_a);
	void c_do_callback ();
};
 
test_class::test_class()
{
 
}
 
void test_class::c_set_object (EIF_REFERENCE obj_a)
{
	if (obj != NULL)
	{
		eif_wean (obj);
	}
	obj = eif_protect (obj_a);
}
 
void test_class::c_set_routine (EIF_POINTER routine_a)
{
	routine = routine_a;
}
 
void test_class::c_do_callback ()
{
	((void (*) (EIF_REFERENCE)) routine) (eif_access (obj));
}

Comments

After having a problem with

patrickr's picture

After having a problem with creating a STRING from a std::string (c++): Here's the solution

cpp_get_text: STRING is
        -- Get some dummy text
    external
        "C++ inline use <string>"
    alias
        "[
         std::string a = "dummy";
         return RTMS(((char*)a.c_str()));
        "]
    end

Note that RTMS is a macro

manus_eiffel's picture

Note that RTMS is a macro and evaluate twice its argument, so for efficiency it should be:

cpp_get_text: STRING is
        -- Get some dummy text
    external
        "C++ inline use <string>"
    alias
        "[
         std::string a = "dummy";
         char *c_str = (char*) a.c_str();
         return RTMS(c_str);
        "]
    end

Syndicate content