Jump to content
  • Advertisement
Sign in to follow this  
ElectroDruid

Problems with RunTime Linking DLLs

This topic is 4719 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

Hello, I'm exploring DLLs for the first time, and I'm having some difficulties getting them to work. I'm creating my DLL with code that looks basically like this:
//mydll.h
__declspec(dllexport) void SomeFunction();

//////////////////////////////

//mydll.cpp
#include"mydll.h"

void SomeFunction()
{
    cout << "All your DLL are belong to us\n" << endl;
}
So far so good. I can load and run this function from a different app in the obvious way:
//mydll.h
__declspec(dllimport) void SomeFunction();

//////////////////////////////

// myDllCallTest.cpp

#include"mydll.h"
#include<conio.h>
#pragma comment(lib, "mydll.lib")

void main()
{
    SomeFunction();
    system("PAUSE");
}
Incidentally, the DLL seems to take a good 5-10 seconds to load and do anything, I don't know if that's normal. Now, I'm trying to load the same DLL I created from the first bit of source into yet another app, this time dynamically. The ultimate goal is to end up with something along the lines of what's described in the MSDN document "DLLs, The Dynamic Way" but in the meantime I'm messing around with one of the basic examples from this doc: http://www.gamedev.net/reference/articles/article928.asp
#include<conio.h>
#include <windows.h> 
#include <stdio.h>

extern "C" void SomeFunction();
typedef void (*MYFUNCTION)(void);

void main()
{
	MYFUNCTION pfnMyFunc=0;

	HINSTANCE hMyDll = LoadLibrary("mydll.dll");

	if(hMyDll != NULL)
	{
		pfnMyFunc= (MYFUNCTION)GetProcAddress(hMyDll, "SomeFunction");

		if(pfnMyFunc== 0)   
		{
			FreeLibrary(hMyDll);
			return;
		}

		pfnMyFunc();

		FreeLibrary(hMyDll);
	}

	system("PAUSE");
}
I don't do the __declspec(dllimport) or the #pragma, I just rely on what's listed about. I get the couple of second pause (like I did with the load-time linking), but no display. From single stepping through the code it seems that the DLL is actually loading, but pfnMyFunc isn't set properly by the GetProcAddress call. Anyone know why that might be? As a side note/related question, what would be a good way to lay out a project in .NET such that I can use one solution which can compile DLLs as well as compile the code that uses them? I'm thinking along the lines of breaking the solution up into a bunch of projects, each one representing a DLL (except one which is the executable code which loads the DLLs), and setting the dependencies such that if you try to compile the executable project, it will first compile any changes it finds in any of the DLLs. Will that work or am I barking up the wrong tree? Thanks in advance for any light you might be able to shed on all this stuff :)

Share this post


Link to post
Share on other sites
Advertisement
I'm doing a similar thing at the moment which is working without any problems. "pfnMyFunc isn't set properly by the GetProcAddress cal" - do you mean that the function isn't being set at all, or to something wrong? If GetProcAddress is failing completely it could be something to do with the name mangling. I don't know what the 'proper' solution to this is, but I found putting a .DEF file in the source directory for the DLL seems to work; the linker picks it up and knows to export the correctly named symbols. Here's mine:


LIBRARY XGEXT_Render2D_Allegro
EXPORTS
XGEXT_Start
XGEXT_Exit
XGEXT_GetInternalName
XGEXT_GetEntity



As for the dependencies, yes, it can be set up like that. I have the DLLs set as dependencies of the main project, and set their output directories to be the location needed for the main executable. They're all in separate projects, but loaded into one main workspace.

EDIT: Put in source tags. Haven't been here for so long...

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
pfnMyFunc starts off with the value of type void* (at least according to my debugger), and the GetProcAddress call doesn't change that, so the if statement straight afterwards picks that up, unloads the library and returns from main().

I made a .def file (I'm guessing it's basically just a text file with the extension changed?), and put it in the source/project directory. It reads:

LIBRARY mydll
EXPORTS
SomeFunction

The linker didn't appear to pick up on it or do anything particularly special. I dragged it into the project workspace as well, but nothing seems to happen.

One thing I forgot to mention, although I don't know if it's relevant is a linker warning I get when building the DLL:
LINK : warning LNK4243: DLL containing objects compiled with /clr is not linked with /NOENTRY; image may not run correctly

I figured that that was reasonable given that my DLL doesn't (and shouldn't) involve a main() of any description. I tried adding /NOENTRY to the linker command line but that just results in an error:
LIBCMTD.lib(crt0.obj) : error LNK2019: unresolved external symbol _main referenced in function _mainCRTStartup

I'm not fussed about the warning, just thought I'd mention it in case it was relevant

Share this post


Link to post
Share on other sites
Shouldn't __declspec(dllexport) be extern "C" __declspec(dllexport)? This is how I've always had to declare it anyway.

Edit: Ah, thats what I did wrong (I was trying it in an app and couldn't get it to work.) I had a typo (as you said). dllimport should be dllexport.

[Edited by - Programmer16 on June 21, 2005 1:13:43 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Programmer16
Shouldn't __declspec(dllimport) be extern "C" __declspec(dllimport)? This is how I've always had to declare it anyway.

It doesn't look like it has to be*. Load-time linking works fine for me either way, but that's not my problem. I still can't get runtime linking to find my functions in the DLL.


* (But I am playing with a really simple example, so it's possible I could have run into problems later)

Share this post


Link to post
Share on other sites
These problems is often because of name mangling, where SomeFunction becomes _SomeFunction@0 or similar. It is the more strange name _SomeFunction@0 that GetProcAddress needs. Try to use the following command line to figure out which name to send to GetProcAddress:
dumpbin /exports mydll.dll

If you use extern "C" linkage and STDCALL calling convention, you will not get any extra mangling of your name, which makes things simpler. You can also use syntax in the DEF-file to customize in which way the functions are exported.

List of different exported names I get (this is kind of compiler specific) with different methods:
__declspec(dllexport) void SomeFunction(); // ?SomeFunction@@YAXXZ
extern "C" __declspec(dllexport) void SomeFunction(); // SomeFunction
__declspec(dllexport) void __stdcall SomeFunction(); // ?SomeFunction@@YGXXZ

And with a def-file looking like this:
LIBRARY mydll
EXPORTS
SomeFunction

it gets the name SomeFunction. You may have to specify the def-file in "Project Properties -> Linker -> Input -> Module Defintion File"

Regarding your warning: /clr means that you use C++ Managed Extensions, which ables you to run managed code and access the objects of the .NET Framework. However, the code automatically run during the initialization of a mixed DLL violates the restrictions for DllMain. This problem is not completely solved by Microsoft yet. Is it necessary to use .NET Framework in your DLL?

[Edited by - EliasAE on June 21, 2005 5:56:52 AM]

Share this post


Link to post
Share on other sites
Got it! EliasAE, you were right in that the DLL contained mangled names because I wasn't exporting as extern "C". (Similarly, Programmer16 was kinda right except that the important part is the export, not the import). I don't seem to need a .def file with the way I'm doing things now, but it's very handy to know how to get the linker to pay attention to one if I need it to. I might well need that in the future.

So I guess the only other mystery is why does my program take so long to start up? I'm only doing runtime linking now, but the program still seems to pause for 5-10 seconds before entering main(). Is that normal?

Share this post


Link to post
Share on other sites
Another, probably very dumb question. Hopefully this is the last one though :o)

Is there any way a DLL can get access to anything in the code which loads it? In other words, can it make use of the global classes and data in my main program? I managed to get my code to compile with a DLL project including a header which declares a variable, but the main program and the DLL seem to bother end up with their own individual copies of the variable which they update independently.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!