Archived

This topic is now archived and is closed to further replies.

.dll troubles

This topic is 5650 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

i wrote some code to load a wave file. everything works great, UNTIL i put everything into a dll & import the functions from it. it''s the SAME CODE, even the SAME PROJECT (i only added the linker-parameter ''/dll'' and changed the output file) and still it doesn''t work. i''m sure, i''ve put all _decl~(import/export) - stuff in the right places. i''ve already had similar troubles, when accessing a static object within an exported object. the access from my app seemed to be different from access on the same object from within .dll-functions. i fixed that by using a pointer to the object instead of a ststic object. that worked (don''t ask me, why !...) i''m getting mad, if i don''t find the bug soon. (ramming my head against everything in sight !! > ) anyone can tell me the differences of .dll-imported & ''normal'' functions ??? plz help ! (my head hurts )

Share this post


Link to post
Share on other sites
After compiling the dll, did you notice the lib file that was also generated? Did you remember to include that in the link with the exe? As IndirectX asks, what exactly isn''t working?

Share this post


Link to post
Share on other sites
yes, sure, i included the .lib-file.

what does not work ? GOOD QUESTION, INDEED !

it''s really strange. i call a readfile-function (that actually only calls fread()). it works for reading the header. then there''s some extra-wav-chunk (added by WaveLabs) that i want to skip.
the skip is an fseek() with the chunk-size.

<<<>>>

then (after skipping) i read the next chunk-info again (into a static header-object), until the ''data''-chunk comes. THIS doesn''t work, when linked to .dll. the read-functions don''t return errors, but they fill my header-object with 0.

that''s really odd to me, since this doesn''t happen, when i don''t use .dll, but just include all .cpp files into my project & remove all __declspec(import) - stuff. everything works perfectly for that case !

THAT''s actually my problem. it may be, that my code has a bug (i''ll find it, i''m sure...) but WHY THE HECK DOES THE .dll MAKE SOMETHING DIFFERENT FROM THE SAME CODE INCLUDED TO THE PROJECT ???

what does a .dll call make, which a standard call doesn''t ??
what''s the difference from .dll to .cpp/.obj ??


THAT''s what i don''t understand... (maybe, when i know, the bug will be easy to find )

Share this post


Link to post
Share on other sites
quote:
Original post by uNiQue0815
but still there''s the question... what does .dll do, that .cpp/.obj doesn''t (or the other way round...)


You''re comparing apples with oranges. cpp files contain source code, obj files contain intermediate compiled code with some compiler/linker information, and dlls have final compiled code. Dlls allow you to basically split your exe file in chunks.

Share this post


Link to post
Share on other sites
quote:
Original post by uNiQue0815
what does a .dll call make, which a standard call doesn't ??
what's the difference from .dll to .cpp/.obj ??


I'll take a stab at this instead.

This explanation is very rough.

When an exe loads, the statically linked dlls are also loaded into the address space of the process. The lib file used to statically link the dll contains information used by the linker to locate the exported dll functions as offsets from the base address of the dll. Offsets are used because a dll may not always load at the desired address, but at whatever address it loads, the offsets will remain constant.

So in your source code when you call a function in a dll, the compiler turns the function name into a symbol that the linker puts into a import table along with the 'fixup' info from the lib file. At load time, the symbols in the import table are jived up with the dll load address, so that they point to where the instructions have actually been loaded into the process. This process involves a little bit more processing time at load, but it's not noticeable and once the dlls are loaded, there is no difference between a call to the dll and a call to an internal function.

When the function is defined in the source and ends up in the obj, the compiled instructions are located in the .text section of the exe (typically). The addresses of functions in this section are in the range 0x00410000++. Addresses of dlls are much farther up in the address space - for example on W2K kernel32.dll loads at 0x77e80000.

Experiment with __declspec(dllexport) in an exe - yes you can export functions from an exe - and then use PEDump or Dependency Walker to examine the results.

For greater details, head over to MSDN, go to MSDN Magazine and take a look at the "Under the Hood" columns. Maybe get a hold of a copy of Jeff Richter's "Advanced Windows" too.

[edited by - lessbread on June 26, 2002 7:08:24 PM]

Share this post


Link to post
Share on other sites
well... ok...

indirectX :
maybe i''ve been a little imprecise about what i meant...
i know, that .cpp holds source and .dll is compiled...
but .cpp will also get compiled once... and i thought (until my troubles with it), that the code compiled from .cpp & linked into an exe should behave equal to a function imported from .dll (same source + __declspec(export/import) + just compiled to .dll). BUT IT DOESN''T !! (or didn''t for me)

my loadfile function worked perfectly when i compiled from .cpp & didn''t work (still same function/source) when linked/imported from .dll ! that''s my problem. i already found the bug in my code but still i wonder, why it works for .cpp-include-case & doesn''t for .dll-import-case... !

LessBread :
thx for explanation... but that also doesn''t really answer my question... it maybe would, IF i hard-coded some functions (maybe even some self-modifying code that (for whatever reason) accesses the wrong memory address for .dll & the right one for .cpp (compiled... hit me for ".cpp" - but i don''t know how else i should name the compiled-linked-into-project-.cpp-files).
but that''s not only veeery unlikely... i also don''t do anything like that. it''s just plain C++-code.

maybe some little example :

/*.h*/
class _export/_import myClass
{
public:
int hallo;
};

class _export/_import myClass2
{
public:
myClass theObject;
bool myFunction();
};

/*.cpp*/
bool _export myClass2::myFunction()
{
theObject.hallo = 0;
}

// compiled to .dll ----

THIS DIDN''T WORK ! BUT THE FOLLOWING DID WORK :

/*.h*/
class _export/_import myClass
{
public:
int hallo;
};

class _export/_import myClass2
{
public:
myClass *theObject;
bool myFunction();
};

/*.cpp*/
bool _export myClass2::myFunction()
{
theObject = new myClass();
theObject->hallo = 0;
}

// compiled to .dll ----


whenever i accessed the exported myClass.theObject (from 1st example) from my App (that (of course) included the .h and the .lib !), i got different result from when the SAME object was accessed within any member function of myClass2;
this didn''t happen with 2nd example (the pointer-solution).
btw: the SAME code (without the _export/_import-stuff) worked PERFECTLY when including the .cpp & compiling... (both examples)

any ideas ? i don''t have any problems using pointers, instead of static objects, but i''d REALLY like to know the reason...

Share this post


Link to post
Share on other sites
Exporting classes from a dll changes the mix somewhat. Since I don't use C++ much, I can't speak to that directly. Even so, it's still going to boil down to addresses and offsets. I suspect that before using the methods from an object located in a dll, a pointer to the object must be obtained first - rather a pointer to an instance of the object. One you have that, the methods are likely offsets from that address. If you're trying to call object methods directly from the dll, then that's likely the source of the troubles - or so it would seem to me.

Here's some faux C source, maybe it illustrates, maybe it doesn't


    
// header containing prototype

int MyFuncFromDll(int i);

// dll source

#include header
int MyFuncFromDll(int i)
{
return i;
}

// exe source

#include <stdio.h>
#include header // link with dll.lib


int MyFuncFromExe(int i)
{
return i;
}

int main(void)
{
int x = 12345678;
printf("x: %d",x);
int y = MyFuncFromExe(x); // has address above 0x00410000

printf("y: %d",y);
int z = MyFuncFromDll(x); // has address close to 0x70000000

printf("z: %d", z);
return 0;
}



Both functions do the same thing, both contain the same instructions. Aside from the names, the differences will be in the addresses of each function. Now if you consider how similar the name of a function is to a function pointer and insert code like this:

printf("Exe form: %p - Dll form: %p", MyFuncFromExe, MyFuncFromDll);

You might be surprised to find that the address of the dll function is not near 0x70000000. What comes out is the address of that function in the import table. So when the function is called, the import table is accessed and the "true" address is retrieved from there, like a pointer pointer. Then the instructions located at the "true" address are executed. The "true" address is figured out when the exe first loads, not when the function is called, so the overhead of calling the function in the dll amounts to dereferencing a "pointer pointer" basically. Try using LoadLibrary, GetProcAddress and you'll see that the address of the returned function pointer is the "true" address of the function.

      
typedef int (*MyFuncT)(int i);
HMODULE mydll = LoadLibrary("dll");
MyFuncT myfunc = (MyFuncT)GetProcAddress(mydll,"MyFuncFromDll");
printf("MyFuncFromDll: %p", myfunc); // someplace around 0x70000000


Note that the address might not really be near 0x70000000 as I just made up that number to show that the dll loads at a very different place in the process address space than the exe itself does. The exe will load at 0x00400000 however so it's quite likely that the address of MyFuncFromExe will be near 0x00410000.

So - throw an object into this mix and you can see where the complications can arise. The object instance is on the heap, the object methods are in the dll, call the methods of the object on the heap, the reference offsets might be all screwed up. I'm not certain what actually occurs at this point because I don't use C++, but I do know that there are some issues regarding exporting classes from dlls as I've seen posts related to the topic before. I think there might be some threads here at gamedev - if you can't find satisfaction here, the topic comes up frequently in the MS newsgroups. Try this query: class dll export group:comp.os.ms-windows.programmer.win32

HHH

// edit: green text ???


[edited by - lessbread on June 27, 2002 5:06:36 PM]

Share this post


Link to post
Share on other sites
mmh... ok... i see my example wasn''t too good...
pretty hard to explain...

but i think i got some basic ideas of what could be a reason, LessBread.

i''ll maybe have to debug the hole thing & search the exact differences in handling direct/.dll calls, their heap/stack/mem & whatever. maybe i''ll find something... didn''t read or write assembly code for a few years now :/

thx for help... i''m going into deeper research

Share this post


Link to post
Share on other sites