Templates and DLLs

Started by
15 comments, last by Grecco 16 years, 9 months ago
Quote:Original post by Spoonbender
Or rethink the bit about putting this in a separate dll.

Well this was all to get around not being able to link to the boost libraries with my borland IDE. I have them (libs) compiled for vs 2005. So I suppose I will need to recompile for BCB, which I'd rather not do...
Advertisement
Quote:Original post by _Sigma
Quote:Original post by Spoonbender
Or rethink the bit about putting this in a separate dll.

Well this was all to get around not being able to link to the boost libraries with my borland IDE. I have them (libs) compiled for vs 2005. So I suppose I will need to recompile for BCB, which I'd rather not do...


Unless you want some monstrosity with callback functions to manipulate stl data in the other environment, you don't have much choice.
Damn - Regex is not supported for the new bcb... So much for standard conformance.
There are some rules that you need to consider when using DLL's and templates (several of these have already been mentioned, but I've grouped them together):

1. A C++ template is a _compile_time_ abstraction which has to be resolved during compilation. If you want _run_time_ abstractions, you need to look at virtual base classes, but you probably know that.

2. Passing classes through DLL interfaces is only possible if their methods are exported by the dll. If they are derived from other classes, those need to be exported as well. Some libraries do export classes through a dll, but most often do it by using the virtual base class "pattern". (Xerces-C comes to mind)

3. Name mangling can become a problem if you export C++ decorated names and try to link with a dll built with a different compiler. That's why many DLL interfaces are built on a "standard C" API (or come with source). Of course, using "extern C" will force you "downgrade" to pure C datatypes.


Looking at your specific problem, you could perhaps solve it by making the DLL statefull in this way:

The vector is contained within the DLL and filled during parsing.
The DLL exposes methods to retrieve the size and contents of the vector, as well as some "clear" method. It could be done something like this:


void dll_function_1(const char* string_to_parse); // parses the string & fills the vector
unsigned dll_function_2(void); // returns the size of the vector
float* dll_function_3(void); // returns a pointer to the first element
void dll_function_4(void); // clears the vector

This is basically a way to expose (part of) the stl::vector interface so your BCB code can get at the data. The downside is that the dll will now contain state and is no longer thread-safe without additional work (i.e. thread-local storage etc), so this might not be an ideal solution based on your needs.

If you find yourself needing to do this for more parts of your API, have another look at your design to see if you perhaps need to move the DLL boundary to a higher hierarchy level in your application (i.e. have it do more work). Usually this will lead to an API that requires less communication, and less is more :-)
Simulation & Visualization Software
GPU Computing
www.organicvectory.com
Quote:Original post by _Sigma
Damn - Regex is not supported for the new bcb... So much for standard conformance.


Back to square one then. I think your best option would be to make an interface that uses only basic data types. I'm not sure exactly what you're going to do, but how about exporting two functions?

//1void  my_function_i_wanted_to_export(const char* something, float** recv);//2void release_my_function_data(float* data);


And then let function 1 build an array of floats that it sets *recv to before returning. After the app is done with the float data (copied it into a real std::vector for further processing or something), it may call function 2 to release the data function 1 allocated.

How does that sound?
Yeah, square one indeed.

El Greco: Thanks for the list. I knew some, but you cleared up some misconceptions/unknowns for me. Thanks.

Quote:I'm not sure exactly what you're going to do
. I need to parse a tabular file with variable column counts. Ie. count be a 2x2 table, or 800x789. Size is known at run time.

I then need to find sums, averages, etc.

My initial idea was to read in a line, parse it using regex (I looked into boost::sprirt, but found it confusing, and I've used regex lots ) and populate the vector grid. But regex is not support for bcb.

My idea is as follows. I'm going to write a dll wrapper for boost::regex. Basically:
int parse(float* list, //memory allocated by the main application          char* line, //the line to parse           int col    //total col count so we don't over write past array boundaries          )

I will have a 2D vector array in the main application, then read in and pass the DLL each line. Create a new std string from the char* to use with regex. Use regex to break it up, use lexical cast<float> to convert each matched string from string to float, and insert into the float array.

This way all the stl stuff can be kept in the main app and I'm not allocating any memory in the dll. After I build the vector line by line, I can do what I need with it.

Does this seem reasonable?
Your idea sounds very reasonable (you probably have already implemented it by now). Your solution also works because the layout of the file you read is known at run-time.

A minor modification you could think about is something that happens often in the Win32 API:

  1. Call the function with an empty buffer to write to, and the function then only scans the input and returns the required buffer size.

  2. Then allocate the buffer and call the function again...


But I personally don't like this system, as the 'hard work' (the parsing) is done twice.
Simulation & Visualization Software
GPU Computing
www.organicvectory.com

This topic is closed to new replies.

Advertisement