calling DLL

G

Guest

I have been successfully calling DLL's using VC++ 6.0 and also using VC++7.1
(.NET). I only mention this because I have never felt comfortable with the
process, but nonetheless it did work. Recently I started calling an unmanaged
DLL from a .NET app. It worked fine. Now I have the situation where I am
trying to call a function in one DLL from another DLL. Both are unmanaged and
are built with VC++7.1. In the calling DLL I set the property
page/linker/general/additional library directories to point to the directory
that contains MyDll.lib and MyDll.dll. The entry point is NOT being found. I
am sure that the signature is correct and that the DLL import/export
modifiers are correct. Everything is being compiled as C (instead of C++).
Any suggestions would be most welcome.

TIA,

Bill
 
W

William DePalo [MVP VC++]

Bill Grigg said:
I have been successfully calling DLL's using VC++ 6.0 and also using
VC++7.1
(.NET). I only mention this because I have never felt comfortable with the
process, but nonetheless it did work. Recently I started calling an
unmanaged
DLL from a .NET app. It worked fine. Now I have the situation where I am
trying to call a function in one DLL from another DLL. Both are unmanaged
and
are built with VC++7.1. In the calling DLL I set the property
page/linker/general/additional library directories to point to the
directory
that contains MyDll.lib and MyDll.dll. The entry point is NOT being found.
I
am sure that the signature is correct and that the DLL import/export
modifiers are correct. Everything is being compiled as C (instead of C++).
Any suggestions would be most welcome.

It may be an issue of compiler name decoration (aka mangling).

For the DLL that contains the function you are trying to call do this:

dumpbin /exports YourDllNameGoesHere.dll

Find the name of the exported function that most closely matches the one
that you are trying to call. Post that here. Then also show the declaration
of that function in the module that makes the call and state whether the
caller is written in C or C++. Chances are someone will spot the error.

Regards,
Will
 
G

Guest

OK here it is from dumpbin:

Dump of file rnavandrpop.dll

File Type: DLL

Section contains the following exports for RNAVandRPOP.dll

0 characteristics
428CED7C time date stamp Thu May 19 15:48:12 2005
0.00 version
1 ordinal base
3 number of functions
3 number of names

ordinal hint RVA
name

1
0 0001A78A Relnav_Exec
2
1 0001A131 fnRNAVandRPOP
3
2 000585F4 nRNAVandRPOP

I am trying to call Relnav_exec. In the dll project it is declared this way:

__declspec(dllexport) void Relnav_Exec(
RNAV_Initial *init,
RNAV_Inputs *inputs,
RNAV_stateOutput *state,
RNAV_TelemetryOutputs *telem);


In the dll project that is try to call it it is declared this way:

__declspec(dllimport) void Relnav_Exec(
RNAV_Initial *init,
RNAV_Inputs *inputs,
RNAV_stateOutput *state,
RNAV_TelemetryOutputs *telem);

Both dll projects use the option "Compile as C code". The error message from
the linker is the following:

TEES error LNK2019: unresolved external symbol __imp__Relnav_Exec referenced
in function _WrapRelnavExec

Actually I just noticed that even though I deleted the reference to the
directory that contains the .dll and .lib I get the same error message. This
implies to me that somehow the DLL is not being located as opposed to the
function declaration being incorrect. As I mentioned in my first post I
placed the path for the DLL in the "Additional libraries directories". Help...


Bill
 
W

William DePalo [MVP VC++]

Bill Grigg said:
OK here it is from dumpbin:

Dump of file rnavandrpop.dll
...
0 0001A78A Relnav_Exec
...
I am trying to call Relnav_exec. In the dll project it is declared this
way:

__declspec(dllexport) void Relnav_Exec(
RNAV_Initial *init,
RNAV_Inputs *inputs,
RNAV_stateOutput *state,
RNAV_TelemetryOutputs *telem);


In the dll project that is try to call it it is declared this way:

__declspec(dllimport) void Relnav_Exec(
RNAV_Initial *init,
RNAV_Inputs *inputs,
RNAV_stateOutput *state,
RNAV_TelemetryOutputs *telem);
Oh boy. With the exception of what looks like a typo in the lower case 'e'
in 'exec' above, the names look OK.
Actually I just noticed that even though I deleted the reference to the
directory that contains the .dll and .lib I get the same error message.
This
implies to me that somehow the DLL is not being located as opposed to the
function declaration being incorrect. As I mentioned in my first post I
placed the path for the DLL in the "Additional libraries directories".
Help...

Then maybe the problem is not so much name mangling as DLL Hell. You should
place the import library (.lib file) created by the linker at the time that
the DLL was built in the libraries directory. Make sure you have only one
copy of the DLL on your system. Then if you are debugging the executable,
you can put the DLL in the same directory as the executable. You didn't
earlier place the DLL in one of the other directories along the PATH did
you?

Alternatively, if you are debugging the DLL, you can go to your project's
Debug property settings. Then in the box labelled "Command" enter the name
of the executable that implicitly loads the DLL. You can also enter any
optional parameters as well as the startup directory.

Regards,
Will
 
T

Tamas Demjen

Bill said:
implies to me that somehow the DLL is not being located as opposed to the
function declaration being incorrect. As I mentioned in my first post I
placed the path for the DLL in the "Additional libraries directories". Help...

The "Additional Library Directories" option is for the linker only, not
for the DLL. You have to set the Configuration -> Debugging -> Working
Directory option, that's where the DLL is loaded from (in addition to
the current directory and directories on your path).

Tom
 
T

Tommy Svensson \(InfoGrafix\)

The "Additional Library Directories" option is for the linker only, not
for the DLL. You have to set the Configuration -> Debugging -> Working
Directory option, that's where the DLL is loaded from (in addition to
the current directory and directories on your path).

What is the difference between putting a library path in the Additional
Library Directories and adding a library under the project node in the
Solution Explorer?

Likewise, is there any difference between #including from directly from code
and adding the include files in the include folder of the Solution Explorer?

/Tommy
 
G

Guest

Will,

Thanks for all of the tips. Unfortunately, nothing helps.

1. The .dll and .lib were not duplicated
2. Both were in the the libraries folder
3. I moved both to the same folder as the calling .dll (no effect)
4. I do use both of the debugging techniques you mentioned in other builds
and they work just fine.
5. Keep in mind that in the configuration that I am try to compile now it is
another .dll that is calling this .dll. In other words I have 2 projects that
are both .dll's and one is trying to call the other.
6. I even added the called .dll project to the calling .dll solution and
that had no effect either.
7. As suggested by another poster I set the "Configuration -> Debugging ->
Working Directory" to the called .dll location and that had no effect.

Should I try loading the called .dll from the calling .dll?

Bill
 
W

William DePalo [MVP VC++]

Bill Grigg said:
Thanks for all of the tips.

You are welcome.
Unfortunately, nothing helps.

Sorry about that.

5. Keep in mind that in the configuration that I am try to compile now it
is
another .dll that is calling this .dll. In other words I have 2 projects
that
are both .dll's and one is trying to call the other.

Only one calls the other, right? There is no circularity here, is there?
Should I try loading the called .dll from the calling .dll?

Are you linking implicitly or calling LoadLibrary()?

_If_ I understand your scenario, the calling DLL needs to find the import
library of the called DLL at link time. The DLL needs to be in a directory
along the path at runtime. The algorithm used to locate the DLL at runtime
is described here:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/loadlibrary.asp

Regards,
Will
 
G

Guest

1. No circularity
2. Implicit linking
3. The called DLL is in the same folder as the calling DLL(along with the
..lib file)
 
G

Guest

Will,

I must be doing something really stupid. I just created a solution with .NET
2003 that had a simple MyProg console app project that was trying to
reference an exported variable in a dll project Adll.dll and it will not
build. I placed the Adll.dll in the same folder as MyProg. Here are the code
snippets below:

In MyProg.cpp:
int _tmain(int argc, _TCHAR* argv[])
{
printf("nAdll= %d\n", nAdll);
return 0;
}

In stdafx.h:
__declspec(dllimport) int nAdll;

In Adll.cpp:
// This is an example of an exported variable
ADLL_API int nAdll=0;

In Adll.h:
extern __declspec(dllexport) int nAdll;

The linker error message is:
MyProg error LNK2001: unresolved external symbol "__declspec(dllimport) int
nAdll" (__imp_?nAdll@@3HA)


There has to be something REALLY fundamental that I am missing here.

Bill
 
W

William DePalo [MVP VC++]

Bill Grigg said:
I must be doing something really stupid. I just created a solution with
.NET
2003 that had a simple MyProg console app project that was trying to
reference an exported variable in a dll project Adll.dll and it will not
build. I placed the Adll.dll in the same folder as MyProg. Here are the
code
snippets below:

In MyProg.cpp:
int _tmain(int argc, _TCHAR* argv[])
{
printf("nAdll= %d\n", nAdll);
return 0;
}

In stdafx.h:
__declspec(dllimport) int nAdll;

In Adll.cpp:
// This is an example of an exported variable
ADLL_API int nAdll=0;

How is ADLL_API defined?

Regards,
Will
 
G

Guest

#define ADLL_API __declspec(dllexport)

Bill


William DePalo said:
Bill Grigg said:
I must be doing something really stupid. I just created a solution with
.NET
2003 that had a simple MyProg console app project that was trying to
reference an exported variable in a dll project Adll.dll and it will not
build. I placed the Adll.dll in the same folder as MyProg. Here are the
code
snippets below:

In MyProg.cpp:
int _tmain(int argc, _TCHAR* argv[])
{
printf("nAdll= %d\n", nAdll);
return 0;
}

In stdafx.h:
__declspec(dllimport) int nAdll;

In Adll.cpp:
// This is an example of an exported variable
ADLL_API int nAdll=0;

How is ADLL_API defined?

Regards,
Will
 
G

Guest

Will,

One more update. When I create a .NET 2003 forms app and declare the dll
entry point as in the following:

[DllImport("D:\\TEES\\TEES\\TEES\\Debug\\TEES", EntryPoint="TestRNAV")]
extern "C" int TestRNAV(char* vectorInitFile, char* vectorInputFile);

It works just fine. I cannot use the same technique in the DLL that calls
the other DLL because first of all the compiler does not like the following
line in the calling DLL:

using namespace System::Runtime::InteropServices;

But even if someone could tell me how to fix that problem, I do not want to
have either DLL compiled with the CLR or even as C++ for that matter because
they need to interoperate with a LINUX environment.

Bill

PS: I believe that I noticed, when playing with Visual Studio 2005 Beta 2
that there was a place in Project Properties to indicate that you could build
without the CLR. Is there the equivalent in .NET 2003?



William DePalo said:
Bill Grigg said:
I must be doing something really stupid. I just created a solution with
.NET
2003 that had a simple MyProg console app project that was trying to
reference an exported variable in a dll project Adll.dll and it will not
build. I placed the Adll.dll in the same folder as MyProg. Here are the
code
snippets below:

In MyProg.cpp:
int _tmain(int argc, _TCHAR* argv[])
{
printf("nAdll= %d\n", nAdll);
return 0;
}

In stdafx.h:
__declspec(dllimport) int nAdll;

In Adll.cpp:
// This is an example of an exported variable
ADLL_API int nAdll=0;

How is ADLL_API defined?

Regards,
Will
 
W

William DePalo [MVP VC++]

Bill Grigg said:
I must be doing something really stupid.

The bad news is that I wish I knew what that is but I don't.

The good news is that I decided to bite the bullet, and create a solution
with VS.Net 2003 that includes both DLL and executable components. I'll send
a ZIP by mail though if it doesn't help you, post here you have a better
chance of getting help in less than the 33 hours since my last reply to you.

Regards,
Will
 
W

William DePalo [MVP VC++]

Bill Grigg said:
One more update. When I create a .NET 2003 forms app and declare the dll
entry point as in the following:

[DllImport("D:\\TEES\\TEES\\TEES\\Debug\\TEES", EntryPoint="TestRNAV")]
extern "C" int TestRNAV(char* vectorInitFile, char* vectorInputFile);

WinForms run on the .Net platform. What you are doing here is marking an
external function with the DllImport attriubte so that the compiler and
runtime for .Net conspire to insert the code the hops the fence fence
between .Net and the the unmanaged side of things, marshalls the arguments,
delegates to the unmanaged external function, and unmarshalls its return.
It works just fine.

I love it when things work. :)
I cannot use the same technique in the DLL that calls
the other DLL because first of all the compiler does not like the
following
line in the calling DLL:

using namespace System::Runtime::InteropServices;

It is always a good idea to qualify words like "choke" with the exact text
of the compiler message. But if it occurs when trying to use .Net classes in
a native application it is a non-starter anyway.
But even if someone could tell me how to fix that problem, I do not want
to
have either DLL compiled with the CLR or even as C++ for that matter
because
they need to interoperate with a LINUX environment.

I should tell you that I know nothing of 'nix, 'nux and 'pux development.
PS: I believe that I noticed, when playing with Visual Studio 2005 Beta 2
that there was a place in Project Properties to indicate that you could
build
without the CLR. Is there the equivalent in .NET 2003?

Sure. From the menu choose Project->Properties. Highlight the General item
under the Configuration folder in the left pane. In the right pane make sure
"Use Managed Extensions" is set to No.

So, I should tell you that you confuse me. :) Earlier you said you were
compiling C source. But in a later post you mentioned a .cpp file extension.
So, assuming C++ is what you are after I created a solution with two console
applications - one executable, one DLL - with VS.Net 2003. This is the
source to the toy DLL:

// Adll.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"

__declspec(dllexport) int nAdll = 46;

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}

__declspec(dllexport) void Relnav_Exec(
void *init,
void *inputs,
void *state,
void *telem)
{
int x = nAdll;
}

This is the source to the toy executable:

// Main.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

__declspec(dllimport) void Relnav_Exec(
void *init,
void *inputs,
void *state,
void *telem);

__declspec(dllimport) int nAdll;


int _tmain(int argc, _TCHAR* argv[])
{
printf("nAdll= %d\n", nAdll);

Relnav_Exec(0, 0, 0, 0);

return 0;
}

It works here.

If you send me an email address (remove ".no.spam" and please don't post my
address in the group) I'll ZIP up the project.

Regards,
Will
 
G

Guest

Hi again Will,

Well I finally got around to a close examination of the solution that you
provided and I noticed that the single substantial difference between your
and mine was that you had an entry in Adll property page Configuration
Properties/Linker/Input/Additional Dependencies that identified the location
of the Bdll.lib. To wit:

$(SolutionDir)Main\Debug\Bdll.lib

When I did the equivalent in my solution my linkage problem was solved.
Thanks for the help!!

Now I have 1 other little issue. When I build and run my solution with the
debugger it build and starts up just fine. When I click on the button that
leads to the calling of my DLL I get and error message that says it cannot be
found. HOWEVER, it really does get found and is called and executes just
fine. I just noticed that if I start the app by double clicking on the
main.exe the problem does not occur. Any thoughts?

Bill
 
W

William DePalo [MVP VC++]

Bill Grigg said:
Well I finally got around to a close examination of the solution that you
provided and I noticed that the single substantial difference between your
and mine was that you had an entry in Adll property page Configuration
Properties/Linker/Input/Additional Dependencies that identified the
location
of the Bdll.lib. To wit:

$(SolutionDir)Main\Debug\Bdll.lib

Read the remarks section of the help entry on LoadLibrary here:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/loadlibrary.asp

It describes the DLL search algorithm. I like to create solutions with
multiple projects that deposit their output files in the same directory so
that everything works without thinking about it in development.
When I did the equivalent in my solution my linkage problem was solved.
Thanks for the help!!

You are welcome.
Now I have 1 other little issue. When I build and run my solution with the
debugger it build and starts up just fine. When I click on the button that
leads to the calling of my DLL I get and error message that says it cannot
be
found. HOWEVER, it really does get found and is called and executes just
fine. I just noticed that if I start the app by double clicking on the
main.exe the problem does not occur. Any thoughts.

I don't know for sure. You may have old .PDB files and such lying around.
I'd clean up the directories manually and/or choose Clean from the Build
menu in the IDE and then rebuild everything.

Regards,
Will
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top