Templates and DLLs

Started by
15 comments, last by Grecco 16 years, 9 months ago
I need to write a generic parsing engine (using boost::regex and boost::spirit) which resides in a DLL. I also need to pass a std::string and std::vector<std::vector<float>> as parameters. When I try to compile, I'm informed that templates cannot be used in functions declared as extern "C". Is there a way around this? I am using VS2005, will be calling it from a Borland C++ builder 2007 application. Language is C++ :) Cheers
Advertisement
Avoid using templates with extern "C". You might be able to get away with writing wrapper classes that you use on both ends. You can probably cast through void * to get around this limitation, but that's dangerous.

There's probably a better way to do this that I don't know of, though. I'd only use those two suggestions as a last ditch effort.
Ra
Be very careful with how you approach this. Since different DLLs can be linked to different runtimes, creating and releasing memory across these runtime boundaries is very dangerous if you are not careful. You also want to watch out for passing templates as arguments across boundaries as well. This, especially for std::string, is very dangerous because the implementation for the template on one compiler might be different than another. It is much safer to pass a const char * than the class itself.
What error code did the compiler output? I've never heard of that issue before and would like to see what the docs say about it.
Quote:Original post by Happy Noodle Boy
What error code did the compiler output? I've never heard of that issue before and would like to see what the docs say about it.


MS C2894
Well I can change the std::string into a char* as Deception666 suggested. I also attempted to get around the vector one by doing the void* cast as well. This fixed those errors, but since I am using templates later on in the function, ie, the boost ones, the compiler balked.

Ra: how does one not use extern "c" when using dlls? I was under the impression this was put into place to stop name mangling which made it impossible to call dll functions?

Quote:Since different DLLs can be linked to different runtimes, creating and releasing memory across these runtime boundaries is very dangerous if you are not careful.
The vector will be passed in by reference, so this should be fine correct? And all other instance variables created within the dll are scoped to the function's lifetime.

So how do I fix this then?
Quote:Original post by _Sigma
Well I can change the std::string into a char* as Deception666 suggested. I also attempted to get around the vector one by doing the void* cast as well. This fixed those errors, but since I am using templates later on in the function, ie, the boost ones, the compiler balked.


I would suggest you use a float* (along with a size) instead of attempting to pass the vector itself as a void* parameter, doing that can only lead to trouble when using different compilers. The data of a vector is guaranteed to be continuous in memory so you could just try:

my_dll_function(my_str.c_str(), &myvector[0], myvector.size());

Quote:
Ra: how does one not use extern "c" when using dlls? I was under the impression this was put into place to stop name mangling which made it impossible to call dll functions?


If you are using the same compiler, it is perfectly fine link C++ to C++ (with mangled names and all) even if part of the code is in another DLL.

Quote:
Quote:Since different DLLs can be linked to different runtimes, creating and releasing memory across these runtime boundaries is very dangerous if you are not careful.
The vector will be passed in by reference, so this should be fine correct? And all other instance variables created within the dll are scoped to the function's lifetime.

So how do I fix this then?


You fix this by using basic data types, as parameters for your DLL exported functions. No classes, no templates, just regular C datatypes such as char* and float*.
Quote:Original post by wack
my_dll_function(my_str.c_str(), &myvector[0], myvector.size());


How do I access the vectors later in the fucnction? The vector being passed in is being modified in the function, so I need access to the push_back() method.

As well, lets say I did want to cast froma void*. ((std::vector<std::vector<float>>)array)->clear();. I'm told this is not a legal cast. I've tried boost lexical_cast as well as reinterpret_cast. Neither can do it...
Quote:Original post by _Sigma
Quote:Original post by wack
my_dll_function(my_str.c_str(), &myvector[0], myvector.size());


How do I access the vectors later in the fucnction? The vector being passed in is being modified in the function, so I need access to the push_back() method.

As well, lets say I did want to cast froma void*. ((std::vector<std::vector<float>>)array)->clear();. I'm told this is not a legal cast. I've tried boost lexical_cast as well as reinterpret_cast. Neither can do it...


You just can't. Borlands stl has no knowledge about how Visual Studio's stl works. Even if you get it to compile, there will be horrible crashes waiting for you. You will just have to think of some other way than passing stl structures around.
Or rethink the bit about putting this in a separate dll.

This topic is closed to new replies.

Advertisement