0

I'm creating Haskell bindings for a C library. However, I want to adapt the calling conventions of the library to something more appropriate for Haskell so I've created a template class which has a static method that invokes the correct method when you use it the following way:

Wrap<decltype(&libraryFunction), &libraryFunction>::call(...);

Where ... denotes the arguments. This is great, the compiler has generated the wrapper code for me apparently. I can even take the address of this function using the & operator so it's apparently just a regular function.

However, Haskell cannot use C++ templates so what I'd like to do is to explicitly instantiate this template for the required functions and export them as regular C function which I can reference from Haskell. I know I could just make stubs that manually invoke this static member function but let's say I don't really feel like it.

Any ideas on how to do this? Portable or non-portable, I'd like to know if it's possible.

Emil Eriksson
  • 2,110
  • 1
  • 21
  • 31
  • 1
    Which will be the name of the function ? – Jarod42 Apr 16 '14 at 14:40
  • Have you tried `extern "C"`? – Yifu Wang Apr 16 '14 at 14:43
  • @Jarod42: I'd like to be able to name the exported function whatever I want. – Emil Eriksson Apr 16 '14 at 14:45
  • @user2912836: That makes no sense for a template definition and I don't know how you would use that for a particular intantiation. Besides, what would the name be? – Emil Eriksson Apr 16 '14 at 14:46
  • 2
    *"and export them as regular C function which I can reference from Haskell"* Then you need a regular C name, and not something with `< template-arguments >` which is mangled somehow. [temp]/4 "A template, a template explicit specialization, and a class template partial specialization shall not have C linkage." So this is only possible as a language extension to C++. – dyp Apr 16 '14 at 15:00
  • 1
    @dyp Put that in an answer so we can vote for it. – Mark B Apr 16 '14 at 15:14
  • Perhaps [this answer](http://stackoverflow.com/a/18409751/315052) is close to what you want to achieve? – jxh Apr 16 '14 at 15:55
  • Have you read http://www.haskell.org/haskellwiki/Cxx_foreign_function_interface ? – dyp Apr 16 '14 at 16:15

1 Answers1

2

This cannot be done portably:

[temp]/4

A template, a template explicit specialization, and a class template partial specialization shall not have C linkage.

Note that this also prevents you from taking a pointer to that function letting Haskell call the function via this pointer: It is not guaranteed that e.g. the calling convention of a C++ function (in the C++ program) is the same that Haskell assumes for the function pointer it gets.

What can be done portably is to export a single extern "C" function that translates between C and C++ language linkage. You can pass function pointers or other kinds of identifiers to Haskell, and Haskell calls this single C function passing the identifier of the function it actually wants to call:

std::map<int, void(*)(int32_t)> functions;

extern "C" interface_fct(int id, int32_t arg)
{
    functions[id](arg);
}

This of course is not very useful for functions with different parameter sets.

You could write something similar to va_args (but safer) to pass arbitrary arguments, but it might be more useful to write something nonportable.

dyp
  • 38,334
  • 13
  • 112
  • 177
  • I was rather certain that this cannot be done portably so I was probably looking for something non-portable. This doesn't matter anyway since the library in question is a OS X system library. – Emil Eriksson Apr 16 '14 at 17:59