Discussion:
My exe is using functions from a DLL which are not exported
(too old to reply)
Mikel
2011-07-22 10:19:59 UTC
Permalink
Hi:
The title summarizes it, but I'll elaborate:
In my app, I use several dlls. They are all (the dlls and the exe) in
the same VS solution, and they are linked together by setting the
project dependencies appropriately.

It was all working and nice. But then I added a function (static) to
one of the classes in one of the dlls, to use it from the exe, and the
linker says it doesn't find it. So I start to check what's going on,
and see that this particular class, and its derived classes are not
exported from the dll (there's no def file, no declspec for these
classes, Dependency Walker shows no exported functions from them...).
But I've been calling functions of those classes from the exe! And
it's been working!

So, what I'm missing? What is the compiler/linker doing to use non
exported functions from a dll? Why doesn't it work for static
functions?

Thanks
Faisal
2011-07-22 10:46:57 UTC
Permalink
Post by Mikel
In my app, I use several dlls. They are all (the dlls and the exe) in
the same VS solution, and they are linked together by setting the
project dependencies appropriately.
It was all working and nice. But then I added a function (static) to
one of the classes in one of the dlls, to use it from the exe, and the
linker says it doesn't find it. So I start to check what's going on,
and see that this particular class, and its derived classes are not
exported from the dll (there's no def file, no declspec for these
classes, Dependency Walker shows no exported functions from them...).
But I've been calling functions of those classes from the exe! And
it's been working!
So, what I'm missing? What is the compiler/linker doing to use non
exported functions from a dll? Why doesn't it work for static
functions?
Thanks
One reason may be your function definitions are in .h file itself. Is
it?

Show your class declaration in the .h file.
Mikel
2011-07-22 10:59:33 UTC
Permalink
Post by Faisal
Post by Mikel
In my app, I use several dlls. They are all (the dlls and the exe) in
the same VS solution, and they are linked together by setting the
project dependencies appropriately.
It was all working and nice. But then I added a function (static) to
one of the classes in one of the dlls, to use it from the exe, and the
linker says it doesn't find it. So I start to check what's going on,
and see that this particular class, and its derived classes are not
exported from the dll (there's no def file, no declspec for these
classes, Dependency Walker shows no exported functions from them...).
But I've been calling functions of those classes from the exe! And
it's been working!
So, what I'm missing? What is the compiler/linker doing to use non
exported functions from a dll? Why doesn't it work for static
functions?
Thanks
One reason may be your function definitions are in .h file itself. Is
it?
Show your class declaration in the .h file.- Ocultar texto de la cita -
- Mostrar texto de la cita -
No. That's what I thought at first, but no. The code is in the cpp
file of the class, or even in its derived classes
CodeVisio
2011-07-23 14:51:31 UTC
Permalink
Post by Mikel
In my app, I use several dlls. They are all (the dlls and the exe) in
the same VS solution, and they are linked together by setting the
project dependencies appropriately.
It was all working and nice. But then I added a function (static) to
one of the classes in one of the dlls, to use it from the exe, and the
linker says it doesn't find it. So I start to check what's going on,
and see that this particular class, and its derived classes are not
exported from the dll (there's no def file, no declspec for these
classes, Dependency Walker shows no exported functions from them...).
But I've been calling functions of those classes from the exe! And
it's been working!
So, what I'm missing? What is the compiler/linker doing to use non
exported functions from a dll? Why doesn't it work for static
functions?
Thanks
Sounds very strange from your description.
Question:
Was the solution + projects created by you? or did you inherit the
solution/project?

Check this:
- the compilation process should have created a .lib file for each dll
file. Since there is no compilation error/warning but a linking one it
seems to me like the .lib file are not aligned with the .h files from
the DLLs. Try to rebuild all projects and check if in the temporary
output folder or in the destination folder ( where there are dll and
exe)there is the .lib file for the relative dll. If you cannot find he
.lib files then no functions, classes, variables are exported from your
dll. At this point the problem reside in your dll settings or on how the
symbols from the DLLs are exported. If you can find the .lib files then
most probably a wrong alignment occurred between the lib files and the
.h files.

- give more information about your issue if you can.
Joseph M. Newcomer
2011-07-24 21:40:23 UTC
Permalink
You just told us why it doesn't find it.

It is declared static, which means the symbol is not visible outside the compilation unit.

There is no .def file or __declspec

This absolutely, positively, beyond any shadow of a doubt, GUARANTEES that the linker will
not find the symbol. So the whole system is working as it is designed to work.

You cannot ever call a non-exported function in a DLL. Why? Because, guess what, that is
what DEFINES the concept of a function you can call. If it isn't exported, it doesn't
exist, as far as anyone outside the DLL is concerned.

It doesn't work for static functions because it is not SUPPOSED to work for static
functions, just as it is not SUPPOSED to work for non-exported functions. Since you
carefully avoided doing anything to make the name visible outside the DLL, guess what, the
name is not visible outside the DLL!
joe
Post by Mikel
In my app, I use several dlls. They are all (the dlls and the exe) in
the same VS solution, and they are linked together by setting the
project dependencies appropriately.
It was all working and nice. But then I added a function (static) to
one of the classes in one of the dlls, to use it from the exe, and the
linker says it doesn't find it. So I start to check what's going on,
and see that this particular class, and its derived classes are not
exported from the dll (there's no def file, no declspec for these
classes, Dependency Walker shows no exported functions from them...).
But I've been calling functions of those classes from the exe! And
it's been working!
So, what I'm missing? What is the compiler/linker doing to use non
exported functions from a dll? Why doesn't it work for static
functions?
Thanks
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
Mikel Luri
2011-07-26 08:06:46 UTC
Permalink
Post by Joseph M. Newcomer
You just told us why it doesn't find it.
It is declared static, which means the symbol is not visible outside the compilation unit.
There is no .def file or __declspec
This absolutely, positively, beyond any shadow of a doubt, GUARANTEES that the linker will
not find the symbol. So the whole system is working as it is designed to work.
You cannot ever call a non-exported function in a DLL. Why? Because, guess what, that is
what DEFINES the concept of a function you can call. If it isn't exported, it doesn't
exist, as far as anyone outside the DLL is concerned.
It doesn't work for static functions because it is not SUPPOSED to work for static
functions, just as it is not SUPPOSED to work for non-exported functions. Since you
carefully avoided doing anything to make the name visible outside the DLL, guess what, the
name is not visible outside the DLL!
joe
Post by Mikel
In my app, I use several dlls. They are all (the dlls and the exe) in
the same VS solution, and they are linked together by setting the
project dependencies appropriately.
It was all working and nice. But then I added a function (static) to
one of the classes in one of the dlls, to use it from the exe, and the
linker says it doesn't find it. So I start to check what's going on,
and see that this particular class, and its derived classes are not
exported from the dll (there's no def file, no declspec for these
classes, Dependency Walker shows no exported functions from them...).
But I've been calling functions of those classes from the exe! And
it's been working!
So, what I'm missing? What is the compiler/linker doing to use non
exported functions from a dll? Why doesn't it work for static
functions?
Thanks
Joseph M. Newcomer [MVP]
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
Maybe I didn't make myself clear, but before adding the static function
that makes the error happen to the class in the dll, I was using other
non-static functions of the same class from the exe, without errors.

That's what made me ask the question, the fact that I seemed to have
been using "non-exported" functions from outside the module.

The "problem" class is an abstract class, and its derived class. None of
them is exported as a whole, and neither are the functions I've been
using from outside the module. They are used in another class which is a
container of pointers of such classes, and which is exported.

class A { }; // Abstract
class B: public A {};
class C: public A {};
class D: public A {};

class EXPORT_CLASS CContainer:public CArray<A*> {};

As I already mentioned, the functions I'm using are defined in the cpp
files, and I can't find them in the exports section of the dll in
Dependency Walker, nor in the imports section of the exe.

It's rather strange. Maybe I'll try to replicate it with a simple
solution, to see what's happening.
Mikel Luri
2011-07-26 10:46:03 UTC
Permalink
Post by Mikel Luri
Maybe I didn't make myself clear, but before adding the static function
that makes the error happen to the class in the dll, I was using other
non-static functions of the same class from the exe, without errors.
That's what made me ask the question, the fact that I seemed to have
been using "non-exported" functions from outside the module.
The "problem" class is an abstract class, and its derived class. None of
them is exported as a whole, and neither are the functions I've been
using from outside the module. They are used in another class which is a
container of pointers of such classes, and which is exported.
class A { }; // Abstract
class B: public A {};
class C: public A {};
class D: public A {};
class EXPORT_CLASS CContainer:public CArray<A*> {};
As I already mentioned, the functions I'm using are defined in the cpp
files, and I can't find them in the exports section of the dll in
Dependency Walker, nor in the imports section of the exe.
It's rather strange. Maybe I'll try to replicate it with a simple
solution, to see what's happening.
I've created a sample solution which reproduces the issue. I've created
pretty much the class structure of my previous post in a dll, then used
it from my exe file.

If you want to take a look at it, you can find it in the following link
(it's a VS2008 solution):
http://www.filedropper.com/exporttest
CodeVisio
2011-07-26 18:56:05 UTC
Permalink
Post by Mikel Luri
Post by Mikel Luri
Maybe I didn't make myself clear, but before adding the static function
that makes the error happen to the class in the dll, I was using other
non-static functions of the same class from the exe, without errors.
That's what made me ask the question, the fact that I seemed to have
been using "non-exported" functions from outside the module.
The "problem" class is an abstract class, and its derived class. None of
them is exported as a whole, and neither are the functions I've been
using from outside the module. They are used in another class which is a
container of pointers of such classes, and which is exported.
class A { }; // Abstract
class B: public A {};
class C: public A {};
class D: public A {};
class EXPORT_CLASS CContainer:public CArray<A*> {};
As I already mentioned, the functions I'm using are defined in the cpp
files, and I can't find them in the exports section of the dll in
Dependency Walker, nor in the imports section of the exe.
It's rather strange. Maybe I'll try to replicate it with a simple
solution, to see what's happening.
I've created a sample solution which reproduces the issue. I've created
pretty much the class structure of my previous post in a dll, then used
it from my exe file.
If you want to take a look at it, you can find it in the following link
http://www.filedropper.com/exporttest
Hi, I downloaded your example and compiled it and it woked as you
explained.
What is inside your project is:
- the dll contains and abstract class A
- two derived classed B and C derived from A.
- a carray class derived CMyCollection of pointers to A's classes. The
CMyCollection is exported in a regular way.

Your question following:

"...But then I added a function (static) to
one of the classes in one of the dlls, to use it from the exe, and the
linker says it doesn't find it"
That's ok. What you're exporting from your dll is only the class
CMyCollection and not A, B and C. So if you add a method on B or C,
whatever method you like, you cannot see it on the exe. The linker gives
the error because you are not allowed to use any B, C methods, because
they are not exported.
Put in other words, what you're playing with in your exe is
CMyCollection and pointers not the single A, B, C classes.
Then if you are asking why you can use the A and A's methods inside the
exe I think because you're using pointers. Indeed you include A.h only
in the exe and the real stuff about B and C's methods are happening
inside the dll (CmyCoollection::Init).

I'll give a simple example:
Move away the concept of c++ class. Suppose your dll is exporting a
single function

tyepdef int (*FnPointer)(int, int)
__declspce( dllexported ) FnPointer* GiveTheNthElement( nth );

You provide to the caller the declaration of FnPointer, as simple of
types of function pointer.
At this point from your dll you're exporting only the
GiveNthElement(...) function. In your exe you can call regularly the
GiveNthElement(...) function and retrieve a pointer.
To use this pointer you don't need the other functions the pointer
retrieved points to, you can call and use the funtion pointer normally,
based on the declaration.

FnPiointer* ptr = GiveTheNthEleemnt( 10 );
int Count = ptr( 0, 10 );

The real stuff happens at run time and not at compile or linking time.

Is it clear?
Mikel Luri
2011-07-27 07:21:42 UTC
Permalink
Ok. I imagined it was something like that. Thanks for the explanation
Joseph M. Newcomer
2011-07-27 17:57:11 UTC
Permalink
Once you posted *exactly* what you were doing, instead of vague handwaves, the problem was
easily understood and answered. It is critical in making reports that you be absolutely
precise about what you are talking about. For example, when you said "I added a static
function", my impression was that you had written

static SomeFunction(...args here...) { ... }

but wheat you should have said is that you added a static method to a derived subclass of
an abstract superclass. Your description was still not precise enough, because you didn't
show exactly the code that was failing, you just gave a sketch of what might have been
code. But you have to be thorough and precise in your problem descriptions.
joe
Post by Mikel Luri
Ok. I imagined it was something like that. Thanks for the explanation
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
CodeVisio
2011-07-28 05:52:05 UTC
Permalink
Post by Joseph M. Newcomer
Once you posted *exactly* what you were doing, instead of vague handwaves, the problem was
easily understood and answered. It is critical in making reports that you be absolutely
precise about what you are talking about. For example, when you said "I added a static
function", my impression was that you had written
static SomeFunction(...args here...) { ... }
but wheat you should have said is that you added a static method to a derived subclass of
an abstract superclass. Your description was still not precise enough, because you didn't
show exactly the code that was failing, you just gave a sketch of what might have been
code. But you have to be thorough and precise in your problem descriptions.
joe
Post by Mikel Luri
Ok. I imagined it was something like that. Thanks for the explanation
Joseph M. Newcomer [MVP]
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
Anyway, I'm agree with Joseph.
It would have been helpful.
Liviu
2011-07-28 04:22:04 UTC
Permalink
Post by Mikel Luri
Maybe I didn't make myself clear, but before adding the static
function that makes the error happen to the class in the dll, I was
using other non-static functions of the same class from the exe,
without errors.
That's what made me ask the question, the fact that I seemed to have
been using "non-exported" functions from outside the module.
The "problem" class is an abstract class, and its derived class. None
of them is exported as a whole, and neither are the functions I've
been using from outside the module. [...]
As I already mentioned, the functions I'm using are defined in the cpp
files, and I can't find them in the exports section of the dll in
Dependency Walker, nor in the imports section of the exe.
In addition to what's been cleared up in the other replies already,
note that you _can_ call _virtual_ methods which are not explicitly
exported from the dll.

As long as (a) the object itself is created inside the .dll so its
vtable is built there, and (b) the virtual method is declared and
accessible in the header your .exe is compiled against, the call will be
routed correctly at runtime through the function pointer in the vtable.

The above doesn't of course apply to static or non-virtual member
functions, which are called directly and thus require either the class
or at least themselves to be explicitly exported.

Liviu
CodeVisio
2011-07-28 06:00:28 UTC
Permalink
Post by Liviu
Post by Mikel Luri
Maybe I didn't make myself clear, but before adding the static
function that makes the error happen to the class in the dll, I was
using other non-static functions of the same class from the exe,
without errors.
That's what made me ask the question, the fact that I seemed to have
been using "non-exported" functions from outside the module.
The "problem" class is an abstract class, and its derived class. None
of them is exported as a whole, and neither are the functions I've
been using from outside the module. [...]
As I already mentioned, the functions I'm using are defined in the cpp
files, and I can't find them in the exports section of the dll in
Dependency Walker, nor in the imports section of the exe.
In addition to what's been cleared up in the other replies already,
note that you _can_ call _virtual_ methods which are not explicitly
exported from the dll.
As long as (a) the object itself is created inside the .dll so its
vtable is built there, and (b) the virtual method is declared and
accessible in the header your .exe is compiled against, the call will be
routed correctly at runtime through the function pointer in the vtable.
The above doesn't of course apply to static or non-virtual member
functions, which are called directly and thus require either the class
or at least themselves to be explicitly exported.
Liviu
It works also for "normal" methods (non-static and non-virtual).
The A class has two accessor methods for the double m_Val member data:
A::Val()
A::Val( double ).

If you call them inside the loop from the
CExportTestDoc::OnTestClickhere()
handler function you can see it works fine too.
Liviu
2011-07-28 06:11:34 UTC
Permalink
Post by CodeVisio
Post by Liviu
As long as (a) the object itself is created inside the .dll so its
vtable is built there, and (b) the virtual method is declared and
accessible in the header your .exe is compiled against, the call will
be routed correctly at runtime through the function pointer in the
vtable.
The above doesn't of course apply to static or non-virtual member
functions, which are called directly and thus require either the
class or at least themselves to be explicitly exported.
It works also for "normal" methods (non-static and non-virtual).
A::Val()
A::Val( double ).
If you call them inside the loop from the
CExportTestDoc::OnTestClickhere()
handler function you can see it works fine too.
Right, yet for a diferent reason - those are inlined and actually
defined (not just declared) in the header.

The OP has been vague as to what was "working" and where exactly
he added the static member which caused it to no longer work. I was
just following up on why some functions could be called without being
explicitly exported.

Nobody
2011-07-25 00:36:24 UTC
Permalink
Post by Mikel
In my app, I use several dlls. They are all (the dlls and the exe) in
the same VS solution, and they are linked together by setting the
project dependencies appropriately.
It was all working and nice. But then I added a function (static) to
one of the classes in one of the dlls, to use it from the exe, and the
linker says it doesn't find it. So I start to check what's going on,
and see that this particular class, and its derived classes are not
exported from the dll (there's no def file, no declspec for these
classes, Dependency Walker shows no exported functions from them...).
But I've been calling functions of those classes from the exe! And
it's been working!
So, what I'm missing? What is the compiler/linker doing to use non
exported functions from a dll? Why doesn't it work for static
functions?
You are not calling the function in the DLL, but inside the EXE itself. You
probably made a LIB version and included that in the final EXE. In these
situations I would use "Clean Solution", which deletes all output
files(OBJ/LIB/DLL/EXE) and rebuild everything. Using Rebuild alone doesn't
delete these files, you have to use Clean Solution.
Nobody
2011-07-25 00:40:25 UTC
Permalink
Using Rebuild alone doesn't delete these files, you have to use Clean
Solution.
Please disregard the above. Rebuild would clean first before rebuilding.
Loading...