V
vpadial
Hello,
I want to build a library to help exporting c++ functions to a
scripting languagge. The scripting language provides a function to
register functions like:
ANY f0()
ANY f1(ANY)
ANY f2(ANY, ANY)
ANY f3(ANY, ANY, ANY)
...
where ANY is an opaque type, with functions available to convert from
and to basic C types.
I would like to avoid writing a wrapper for any function I have to
export.
My first try (restricted to functions of one argument, but can easily
be extended):
//------------------------------------------------
template <class T_return, class T_arg, T_return (*fn)(T_arg)>
struct Translator1 {
static ANY proc(ANY arg)
{
T_arg a = from_any<T_arg>(arg); // Conversion from ANY to arg type
T_return r = to_any<T_return>((*fn)(a)); // Conversion from return
type to ANY
return r;
}
};
int foo(int a) { return a*10; }
typedef Translator1<int, int, foo> FN;
c_reg_function( FN:roc );
//-----------------------------------------------------
Ok, that works ! But it would be fine to let the compiler guess the
type of the arguments:
//--------------------------------------------------------
template <class T_return, class T_arg>
void export_fn(T_return (*fn)(T_arg))
{
c_reg_function(Translator1<T_return, T_arg, fn>:roc(arg));
}
export_fn(foo);
//-----------------------------------------------------------------
But now, something goes wrong (g++ v3.3) !!!
test.cc: En function `void export_fn(T_return (*)(T_arg)) [with
T_return = int,
T_arg = int]':
test.cc:43: instantiated from here
test.cc:33: error: `fn' is not a valid template argument
test.cc:33: error: it must be the address of a function with external
linkage
test.cc:33: error: `arg' undeclared (first use this function)
test.cc:33: error: (Each undeclared identifier is reported only once
for each
function it appears in.)
test.cc:33: error: `<type error>' is not a class type
I'm afraid that the compiler cannot expand a template class within a
template function with fewer template arguments ! I cannot use
functors because the register function expects C functions !
Any good idea ? I cannot think of any solution that avoids the use of
dirty preprocesor macros.
Thanks !!!
A reduced version of the code is provided so that you can try
yourself:
////////////////////////////////////////////
#include <iostream>
using namespace std;
typedef long ANY;
void c_reg_function(ANY (*fn)(ANY)); // external c library function
void c_reg_function(ANY (*fn)(ANY))
{
cout << "Registro: " << (*fn)(2) << endl;
}
template<class T> ANY to_any(T); // ANY conversion functions
template<class T> T from_any(ANY);
template<> int from_any(ANY a) { return a; }
template<> ANY to_any(int a) { return a; }
template <class T_return, class T_arg, T_return (*fn)(T_arg)>
struct Translator1 {
static ANY proc(ANY arg)
{
T_arg a = from_any<T_arg>(arg);
T_return r = to_any<T_return>((*fn)(a));
return r;
}
};
template <class T_return, class T_arg>
void export_fn(T_return (*fn)(T_arg))
{
c_reg_function(Translator1<T_return, T_arg, fn>:roc(arg));
}
int foo(int a) { return a*10; }
int main(int argc, char** argv)
{
typedef Translator1<int, int, foo> FN;
c_reg_function( FN:roc );
export_fn(foo);
}
/////////////////////////////////////7
I want to build a library to help exporting c++ functions to a
scripting languagge. The scripting language provides a function to
register functions like:
ANY f0()
ANY f1(ANY)
ANY f2(ANY, ANY)
ANY f3(ANY, ANY, ANY)
...
where ANY is an opaque type, with functions available to convert from
and to basic C types.
I would like to avoid writing a wrapper for any function I have to
export.
My first try (restricted to functions of one argument, but can easily
be extended):
//------------------------------------------------
template <class T_return, class T_arg, T_return (*fn)(T_arg)>
struct Translator1 {
static ANY proc(ANY arg)
{
T_arg a = from_any<T_arg>(arg); // Conversion from ANY to arg type
T_return r = to_any<T_return>((*fn)(a)); // Conversion from return
type to ANY
return r;
}
};
int foo(int a) { return a*10; }
typedef Translator1<int, int, foo> FN;
c_reg_function( FN:roc );
//-----------------------------------------------------
Ok, that works ! But it would be fine to let the compiler guess the
type of the arguments:
//--------------------------------------------------------
template <class T_return, class T_arg>
void export_fn(T_return (*fn)(T_arg))
{
c_reg_function(Translator1<T_return, T_arg, fn>:roc(arg));
}
export_fn(foo);
//-----------------------------------------------------------------
But now, something goes wrong (g++ v3.3) !!!
test.cc: En function `void export_fn(T_return (*)(T_arg)) [with
T_return = int,
T_arg = int]':
test.cc:43: instantiated from here
test.cc:33: error: `fn' is not a valid template argument
test.cc:33: error: it must be the address of a function with external
linkage
test.cc:33: error: `arg' undeclared (first use this function)
test.cc:33: error: (Each undeclared identifier is reported only once
for each
function it appears in.)
test.cc:33: error: `<type error>' is not a class type
I'm afraid that the compiler cannot expand a template class within a
template function with fewer template arguments ! I cannot use
functors because the register function expects C functions !
Any good idea ? I cannot think of any solution that avoids the use of
dirty preprocesor macros.
Thanks !!!
A reduced version of the code is provided so that you can try
yourself:
////////////////////////////////////////////
#include <iostream>
using namespace std;
typedef long ANY;
void c_reg_function(ANY (*fn)(ANY)); // external c library function
void c_reg_function(ANY (*fn)(ANY))
{
cout << "Registro: " << (*fn)(2) << endl;
}
template<class T> ANY to_any(T); // ANY conversion functions
template<class T> T from_any(ANY);
template<> int from_any(ANY a) { return a; }
template<> ANY to_any(int a) { return a; }
template <class T_return, class T_arg, T_return (*fn)(T_arg)>
struct Translator1 {
static ANY proc(ANY arg)
{
T_arg a = from_any<T_arg>(arg);
T_return r = to_any<T_return>((*fn)(a));
return r;
}
};
template <class T_return, class T_arg>
void export_fn(T_return (*fn)(T_arg))
{
c_reg_function(Translator1<T_return, T_arg, fn>:roc(arg));
}
int foo(int a) { return a*10; }
int main(int argc, char** argv)
{
typedef Translator1<int, int, foo> FN;
c_reg_function( FN:roc );
export_fn(foo);
}
/////////////////////////////////////7