Advertisement

Why limit to C if you programm in C++????

Started by November 14, 2000 11:46 AM
7 comments, last by Sim 24 years, 1 month ago
Hello you! I know you all are tired of Dll's, but I have a problem, I can't solve Look directly at my Dll header code: #ifndef _MAIN_H_ #define _MAIN_H_ #define DLLEXPORT extern "C" __declspec(dllexport) DLLEXPORT int DrawScene(void); DLLEXPORT void KillRenderer(void); DLLEXPORT void ReSizeScene(int,int); DLLEXPORT BOOL InitRenderer(PWNDPROC,char*,int,int,int,bool); DLLEXPORT void Update(void); #endif ----------------------------------------------------------------- Now look at my Exe's header: int (*DrawScene)(); void (*KillRenderer)(); void (*ReSizeScene)(int,int); BOOL (*InitRenderer)(PWNDPROC,char*,int,int,int,bool); void (*Update)(); ----------------------------------------------------------------- And finally the loading-code: void LoadDlls(void) { hRenderer = LoadLibrary("Renderer.dll"); if(hRenderer==NULL) { MessageBox(NULL,"Can't Load Renderer.dll.", "ERROR",MB_OK|MB_ICONEXCLAMATION); exit(1); } DrawScene = (int(*)())GetProcAddress(hRenderer,"DrawScene"); KillRenderer = (void(*)())GetProcAddress(hRenderer,"KillRenderer"); ReSizeScene = (void(*)(int,int))GetProcAddress(hRenderer,"ReSizeScene"); InitRenderer = (BOOL(*)(PWNDPROC,char*,int,int,int,bool))GetProcAddress(hRenderer,"InitRenderer"); Update = (void(*)())GetProcAddress(hRenderer,"Update"); if (!DrawScene) { MessageBox(NULL,"Can't Load Function 'DrawScene'","ERROR", MB_OK| MB_ICONEXCLAMATION); FreeLibrary(hRenderer); exit(1); } if (!KillRenderer) { MessageBox(NULL,"Can't Load Function 'KillRenderer'","ERROR", MB_OK|MB_ICONEXCLAMATION); FreeLibrary(hRenderer); exit(1); } if (!ReSizeScene) { MessageBox(NULL,"Can't Load Function 'ReSizeScene'","ERROR", MB_OK|MB_ICONEXCLAMATION); FreeLibrary(hRenderer); exit(1); } if (!InitRenderer) { MessageBox(NULL,"Can't Load Function 'InitRenderer'","ERROR", MB_OK|MB_ICONEXCLAMATION); FreeLibrary(hRenderer); exit(1); } if (!Update) { MessageBox(NULL,"Can't Load Function 'Update'","ERROR", MB_OK|MB_ICONEXCLAMATION); FreeLibrary(hRenderer); exit(1); } } All the code above works fine! But maybe you've noticed, that all Dll functions return and get only C-types. But I want f.e. to return a class, this is not C compatible! So I changed this line: #define DLLEXPORT extern "C" __declspec(dllexport) to -> #define DLLEXPORT __declspec(dllexport) Now I can compile the code, but my loadingfunction doesn't find functions anymore! How do I have to change the code to get the address from C++ functions in a dll? Thank you! Edited by - Sim on 11/14/00 11:48:54 AM
If you want to export classes, you need to have the class definition both in the DLL and your program. Just like a static library. The one problem here is that it doesn''t work with DLLs unless you are using MSVC++ and define your class as exported. I know this works for load-time linking, probably for run-time too. Hope that helps, because if it does, it will be the first time in a couple weeks my signature makes sense.

--------------------


You are not a real programmer until you end all your sentences with semicolons; (c) 2000 ROAD Programming


You are unique. Just like everybody else.

Yanroy@usa.com

Visit the ROAD Programming Website for more programming help.

--------------------

You are not a real programmer until you end all your sentences with semicolons; (c) 2000 ROAD Programming
You are unique. Just like everybody else.
"Mechanical engineers design weapons; civil engineers design targets."
"Sensitivity is adjustable, so you can set it to detect elephants and other small creatures." -- Product Description for a vibration sensor

Yanroy@usa.com

Advertisement
WTF?
( wow, what have I gotten into )
That''s some wild stuff, you look like you might be able to help me. Peep my post on this page.

-Sage
To export a class use:

class DLLEXPORT CMyClass{};

To export a function within a class try this:

class CMyClass
{
DLLEXPORT void Run();
};

DLLEXPORT void CMyClass::Run(){}

I think that might work, I was messing with dlls a while ago but I don''t remember if the above is correct. If not post correct solution please.
Ok, just tried the above and it works. Forgot to put "public:" before member function Run(), oh well It only works for implicitly loaded libs i.e. import libs.

I don''t think you can export a class or class member function from dynamically loaded lib because of the name mangling done by c++. Specifically c++ supports function overloading and it marks each function with the same name differently. If you had two functions with the same name but different params. types and you exported it with "C" linking which one would the linker choose? If I''m wrong then please someone correct me. Thanks.
That is my problem!
I DO NOT accept that you can't export f.e. a function like this:

CMODEL LoadModel(char * filename)
{
//Some code here//
return loadmodel;
}

Because you ARE programming in C++ and NOT in C! You are using MSVC++!
The MSDN says that this 'extern "C"' ( __declspec(dllexport))
is just needed, IF you try to import the DLL with a programm which is written in C.
But my programm is written in C++!
So I need to change something, either the DLLEXPORT definition, or the loading code: GetProcAddress(hRenderer,"Function");

ANY HELP WOULD BE NICE!

Edited by - Sim on November 15, 2000 3:06:57 PM
Advertisement
This is basically what COM accomplishes.

What you do is, in the library header you declare the class interface then export a function to obtain an interface, and one to destroy an interface.

Something like this:

  // somelib.h/////// someclassclass CSomeClass{public: // ...private: // ...};extern "C"{// obtain interfaceint DLLEXPORT GetInterface (CSomeClass** p);int DLLEXPORT DeleteInterface (CSomeClass** p);}// end header[/source]The implementation of these functions go in the lib source like so:[source]// implement CSomeClass here// ...// interface functionsint DLLEXPORT GetInterface (CSomeClass** p){    // valid parameter check.    if (!p || !*p)        return 0;    // allocate class instance.    *p = new CSomeClass;    return 1;}int DLLEXPORT DeleteInterface (CSomeClass** p){     // parm check     if (!p || !*p)          return 0;     // destroy interface.     delete *p;     *p = NULL;     return 1;}  


Now you can use the .dll to obtain instances of classes within the .dll. The class doesn''t have to be exported because the interface is defined in the library header, which is all it needs to know when dealing with pointers.

Hope this helps.


--------------------------
I guess this is where most people put a famous quote...
"Everything is funnier with monkey''''s" - Unknown
--------------------------I guess this is where most people put a famous quote..."Everything is funnier with monkey''s" - Unknown
You can omit the extern "C" on a function-export declaration if you figure out how the compiler mangles the function name and then you use the mangled name in your call to GetProcAddress

ex,
  // In the dll:__declspec(dllexport) int foobar(){    return 1;};// In some other module:int (*foo)() = GetProcAddress(hDllInstance, "?foobar@@YAHXZ");  

I haven''t really tested this, but it *should* work...
And remember: the name-mangling is in no way standardized, it is most likely different between compilers and might change between versions of the same compiler (the mangling of "foobar" above was done by MSVC++ 6.0)...

I wouldn''t reccomand using this method though, using COM interfaces as someone suggested above is much cleaner...

(tip: use LINK.EXE /DUMP /EXPORTS YourDll.DLL to find out what the mangled names in a .dll (or .exe) are)
quote: Original post by Sim

Now I can compile the code, but my loadingfunction doesn''t find functions anymore!
How do I have to change the code to get the address from C++ functions in a dll?


Use a utility like TDUMP to list all exported names in the DLL. They might appear as something like "MyFunction@24". Do a GetProcAddress() that name and it should find it.



Steve ''Sly'' Williams
Tools Developer
Krome Studios
Steve 'Sly' Williams  Monkey Wrangler  Krome Studios
turbo game development with Borland compilers

This topic is closed to new replies.

Advertisement