Re: extern "C" and C++ conventions when passing parameters
Michael Tiomkin wrote:
1. Define an abstract class with virtual methods instead of your
functions,
2. put an object of a derived class in your library,
3. receive a ptr to this object using 'GetProcAdress' or whatever
exists on your particular OS.
4. Use this object.
This is exactly the method I use. If you call the abstract base class a
struct instead of a class you can also provide a C interface to it with
a forward declaration and a series of functions equivalent to the
public members of the class
Of course your C wrapper may require also to change the uses of some of
the parameters. Functions that return newly created strings can be
wrapped by a simple "struct":
struct string_wrapper; /* implementation has a std::string member */
const char * string_c_str( const string_wrapper * ); /* calls c_str of
member */
size_t string_size( const string_wrapper * ); /* calls size of member
*/
and any other methods you choose to implement but the above is probably
quite adequate.
Note that providing such a C interface not only allows your library to
be used with C. It allows it to be used with other languages too that
can access C libraries (including D).
Not only that but your library is more portable to C++ too! You can
have the library compiled with Visual Studio 8.0 using Dinkumware STL
and the client compiled with gnu using their STL and they will work
with each other. No problems with name-mangling.
Recall that 'GetProcAdress' can also give your a ptr to a variable,
and name mangling doesn't apply to object names.
I prefer this method because using 'extern "C"' is confusing in this
case, it makes your program less readable, and disallows using
functions with the same name and different prototype in the same
library.
Under Windows it's not such an important matter because GetProcAddress
returns FARPROC which will obviously be designed by Microsoft to be big
enough to hold a function pointer. Under POSIX the equivalent dlsym
returns void *. There is a statement that void* here must be big enough
to hold a function pointer but I'm still wary of doing it.
I have a class called DLObject that all exported symbols must derive
from. That doesn't mean that all my interfaces derive from it because
actually the exported symbols are all factories and what they create
are not derived from DLObject. What it does allow me to do is
statically cast void * to DLObject* and then dynamically cast to the
type I actually want it to be. (To do this, of course, I have to use a
C++ interface and by casting there is also a restriction of working in
the same compiler environment etc).
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]