• ### Announcements

#### Archived

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

# my first dll doesn't work

## Recommended Posts

Here are the two projects built seperately:

//myapp.cpp
//a console project
//trys to link and call dll at run-time

#include <windows.h>
#include <stdio.h>

//I tried extern "C" {} on this, but didn't help
__declspec(dllimport) void myPrintString(char *string);

typedef void (*myPrintStringPtr)(char *string);

void main(void)
{
if(dll != NULL)
{
if(!myPrint)
{
FreeLibrary(dll);
}
else
{
myPrint("I'm supposed to see this, but I'm not");
printf("If you see this, then I got the address of the function, right???");
FreeLibrary(dll);
}
}

//mydll.cpp
//I put the output dll into the release or debug directory of myapp.cpp

#include <stdio.h>

__declspec(dllexport) void myPrintString(char *string);

void myPrintString(char *string)
{
printf("%s \n", string);
}


That should compile, but I just made that up for simplicity. No matter what I try to call in my exported-frm-dll function, it won't get called... I tried doing this in Win32 app and in console. I can run it and I can verify that I loaded the library and got the exported function with GetProc, but I can't call it>_< Anyhow, I'm glad I caught these problems now, before I started my actual project around a dll. Edit: why aren't the source tags working? [edited by - temp_ie_cant_thinkof_name on March 21, 2004 5:33:25 PM]

##### Share on other sites
EDIT TO ABOVE: Actually, I DID NOT get as far as the printf statement. So, I''m not linking, and I''m not calling GetProc. Does anyone have any idea why? I put the dll in the same directory as the app''s exe, and the system is supposed to search there first...

##### Share on other sites
SiCrane    11839
Did you try using "mydll.dll" instead of just "mydll"?

##### Share on other sites
CORRECTION AGAIN: LoadLibrary() is returning success, so I''m linking, but GetProcAddress() is failing. That''s where I need help. I''m going to try ''extern "C" {} again on the imported prototype.

##### Share on other sites
quote:
Original post by SiCrane
Did you try using "mydll.dll" instead of just "mydll"?

All, the examples I''ve seen show "nameofdll" w/o the externsion. So I guess LoadLibrary() knows what''s meant. But just in case, I''ll try that even though LoadLib() says it''s working, hmmm...

##### Share on other sites
SiCrane    11839
Well that was a suggestion for when you said that you LoadLibrary() wasn''t working. What does GetLastError() say after a fail call?

##### Share on other sites
Okay, the extension part in the string (".dll"), doesn''t matter, and the extern "C" doesn''t matter. This is what I''ve deduced. Question: in my test app, I''m sending the file name as a string with space characters in it, because that''s what I named the dll ("My Dll Blah"). Does LoadLibrary() mind the spaces??? I''ll get back to you with GetLastError, hold on.

##### Share on other sites
Oluseyi    2103
quote:
Original post by temp_ie_cant_thinkof_name
I shouldn''t think so, given that Windows supports spaces in filenames generally and that your call to LoadLibrary returns successfully.

##### Share on other sites
I called GetLastError() after GetProcAddress() failure, and it gave the int error value 127, which in MSDN is
ERROR_PROC_NOT_FOUND -- The specified procedure could not be found. -- 127

##### Share on other sites
SiCrane    11839
Did you try doing a exported symbol dump from your dll to make sure that the symbol name you''re using is actually the symbol name of your function? It could be an issue with name mangling.

If that is the problem, my personal preferred solution is to add a .def file to when you link the dll.

##### Share on other sites
Oluseyi    2103
quote:
Original post by temp_ie_cant_thinkof_name
__declspec(dllexport) void myPrintString(char *string);

void myPrintString(char *string)
{ ... }
Declaration and definition signatures don''t match.

##### Share on other sites
Oluseyi    2103
quote:
Original post by SiCrane
It could be an issue with name mangling.
Exactly. The difference in calling conventions between declaration and definition could modify the actual entry into the export table.

##### Share on other sites
Okay, I''m going to make a new, clean project for both the app and dll, to get rid of some variables. One question: the option in VS.NET to "Export Symbols (only for dll)"-- should I select that or not? I think I selected that option when making this project, and I don''t know where to change it back, so I''m going to make one with and one w/o to test.

##### Share on other sites
SiCrane    11839
quote:
Original post by Oluseyi
quote:
Original post by temp_ie_cant_thinkof_name
__declspec(dllexport) void myPrintString(char *string);

void myPrintString(char *string)
{ ... }
Declaration and definition signatures don''t match.

Actually, that doesn''t matter. Due to the joy of the way that the linkage specifier propogates, only the declaration needs to be declared __declspec(dllexport); the apparant function signature of the definition doesn''t need to match. In actuallity __declspec(dllexport) is not actually a part of the function signature, so does not contribute to name mangling.

##### Share on other sites
The "Export Symbols" option I was talking about didn't change anything when I selected, it, but I also made an empty project. I'll have to check again to see if that option generates a mod def file for you. But Here's what I'm testing, and I'm getting the PROC_NOT_FOUND error:
A0_MYAPP.exe
/*Main.h:#include <windows.h>#include <stdio.h>__declspec(dllimport) void testInteger(void);*/#include "Main.h"typedef int (*TestFunc)(void);TestFunc getTestInt;HINSTANCE h_dll;void main(void){	h_dll = LoadLibrary("A0_MYDLL");	if(h_dll != NULL)	{		getTestInt = (TestFunc)GetProcAddress(h_dll, "testInteger");		if(!getTestInt)		{			printf("%d\n", GetLastError());			FreeLibrary(h_dll);		}		else		{  			printf("%d\n", getTestInt());//should print 47 if successful			printf("--Is 47 if successful");		}	}	else	{			printf("%d\n", GetLastError());	}}

A0_MYDLL.dll
/*Main.h:#include <windows.h>#include <stdio.h>__declspec(dllexport) int testInteger(void);*/#include "Main.h"int testInteger(void){	return 47;}

EDIT: urgh, source tags

[edited by - temp_ie_cant_thinkof_name on March 21, 2004 6:46:54 PM]

##### Share on other sites
SiCrane    11839
If that''s all you''re doing the the name being exported by your DLL is probably something screwy like "?testInteger@@YAHXZ". Run dumpbin /exports on your DLL and see what it spits out.

##### Share on other sites
I ran dumpbin on my dll and it gave:
ordinal hint RVA       name      1     0 000116F4 ?testInteger@@YAHXZ

EDIT: I read a gamedev article that said something about 'extern "C" {}'ing the import decleration in my client app to force the C nameing style or something... well I thought it was just for older compilers... Maybe NOW, I'll try re- extern "C"'ing ... I'll get back to you. One question: do I have to exter "C" in my dll as well? Because the article just had it on the client app decl. I'll try both, anyway.

[edited by - temp_ie_cant_thinkof_name on March 21, 2004 7:04:59 PM]

##### Share on other sites
SiCrane    11839
As I said, it looks like you''re being bitten by name mangling.

One option is to use that "?testInteger@@YAHXZ" string to get the function, or you can try to get rid of the name mangling. As I said before, my preferred method of doing so is adding a .def file to the dll project.

##### Share on other sites
Okay, I fixed it. You have to extern "C", on every declaration of the exported function "testInteger," even around the definition. I don''t know if you have to do the same or not to the imported decl, but I did in the test, and it works. Now, this should compile (and WORK):

A0_MYAPP.exe
/*Main.h:#include <windows.h>#include <stdio.h>extern "C"{__declspec(dllimport) void testInteger(void);}*/#include "Main.h"typedef int (*TestFunc)(void);TestFunc getTestInt;HINSTANCE h_dll;void main(void){	h_dll = LoadLibrary("A0_MYDLL");	if(h_dll != NULL)	{		getTestInt = (TestFunc)GetProcAddress(h_dll, "testInteger");		if(!getTestInt)		{			printf("%d\n", GetLastError());			FreeLibrary(h_dll);		}		else		{  			printf("%d\n", getTestInt());//should print 47 if successful			printf("--Is 47 if successful");		}	}	else	{			printf("%d\n", GetLastError());	}}

A0_MYDLL.dll
/*Main.h:#include <windows.h>#include <stdio.h>extern "C"{__declspec(dllexport) int testInteger(void);}*/#include "Main.h"extern "C"{int testInteger(void){	return 47;}}

##### Share on other sites
Okay, problem fixed. I found that in VC++ 6.0 under VS.NET IDE 2003, you only need to ''extern "C" {}'' on the declaration of the exported function. So if you have a declaration header for exported funcs and a src file with the definitions you don''t need to put the extern "C" aroudn the definition, only the declaration in the header needs one. You can however, extern "C" everything, including the import decl in the client app and the definition decl in the dll, and it still works, but is not needed. So All I have to do now (to avoid making a def file) is in my export header do
extern "C"{   __declspec(dllexport) int testInteger(void);//....rest of exported funcs}

Thanks SiCrane and Oluseyi for your help.

##### Share on other sites
Oluseyi    2103
quote:
Original post by SiCrane
Actually, that doesn''t matter. Due to the joy of the way that the linkage specifier propogates, only the declaration needs to be declared __declspec(dllexport); the apparant function signature of the definition doesn''t need to match.
Interesting. I thought that the linkage specifier would yield an effect roughly equivalent to extern "C", resulting in no C++ name mangling.

You live, you learn.