Jason Wilborn

I'm new to Visual Studio (I have VS 2005 Standard Edition) and I'm trying to learn how to code a DLL with some standard functions I use instead of including a cpp file into every project that needs it. Using the help I got a DLL to work with a Win32 project using __declspec(dllexport) and __declspec(dllimport). When I try a Windows Form Application I get lots of errors with the linker because of the CLR from what I can tell. I tried various things I read and could never get it to work. I decided to try my hand at a .def file and after reading up on how you write it up I have some questions.

Can you export overloaded functions using a .def file From what I read I have to include extern "C" to keep C++ name mangling from happening but yet the mangling is what allows the different overloaded versions to be told apart. Or am I missing something Also, when you list the function name in the .def file from the examples I've seen you just list the name not the arguments so how do you handle overloaded functions if you can even export them

On a different aspect of DLLs I noticed something odd. I had defined my functions in a .cpp file seperate from the main dll cpp file Visual Studio created. When I compile it in debug it creates a dll and the lib file and works fine (with a Win32 project). When i compile it in release it creates the dll but not the lib file, so I can't use that as a dependency in another program. I moved the functions to the main cpp and did away with the seperate cpp file and recompiled both debug and release and the dll and lib were created. Why isn't a lib file created if I have functions defined in a seperate .cpp file The function prototypes were listed in the main .h file in both cases.

 

 



Re: Visual C++ Language DLL questions with Visual Studio using C++

Alexander Stoyan



Try the next record:

EXTERN_C __declspec(dllexport) void ExportedFunction()
{
// here is your managed code
}


___________________________________________________
Best regards,
Alexander Stoyan

E-mail: alexander.stoyan@gmail.com
MSN: alexander.stoyan@gmail.com
ICQ: 295663150





Re: Visual C++ Language DLL questions with Visual Studio using C++

Mike Danes

"When I try a Windows Form Application I get lots of errors with the linker because of the CLR from what I can tell"

What errors And what type of project it the dll file, Win32 or CLR

"I read I have to include extern "C" to keep C++ name mangling from happening but yet the mangling is what allows the different overloaded versions to be told apart".

Correct, without name mangling you cannot export overloaded functions (and many other things that are C++ related). It is possible to export overloaded functions using a def file but you need to know the mangled name and you need to export using different names. For example for functions:

int foo(int a)

{

return 42;

}

int foo(int a, int b)

{

return 42;

}

You will need to write the following in the def file:

EXPORTS

foo1= foo@@YAHH@Z

foo2= foo@@YAHHH@Z

One way to find out the mangled name of your functions is to make the linker generate a map file (go to Project Properties, Configuration Properties, Linker, Debugging, Generate Map File). You will find a file with a .map extension in the output directory of your solution and you can search in it for mangled names that contain your function name (foo in this example).

Keep in mind that the way name mangling is done is not a standard and it can change from one compiler version to another (so you may need to update the def file if it happens).

"Why isn't a lib file created if I have functions defined in a seperate .cpp file "

The most common reason for a lib file not being created is that there are no exported functions. That can happen if you did some compiler settings (preprocesor definitions for example) only for a particular .cpp file or for a particular build configuration (debug or release).





Re: Visual C++ Language DLL questions with Visual Studio using C++

Simple Samples

There really is a lot of useful information in the documentation; see DLLs and the many sub-topics. Most of what Mike Danes said is in the documentation.

One problem with exporting member functions for use by programs that are not written using C++ is "this". Every instance of a C++ class has a "this" pointer. Non-C++ programs, including C programs, don't know what the this pointer is and they don't know what a this pointer value is. When a C++ member (of a class) function is called, there is always a this pointer as the first parameter. You don't see it; C++ hides that parameter from us, but it is there. Unless the member function is a static member function.

So if you were to be able to determine the mangled name, the calling program needs to know the this pointer and there are various peculiarities of C++ classes that other compilers would not know about. I am nearly certain that if a program calls a C++ class member function then the class member function must be static, and you will probably need to have a way for the static member function to find the instance of the class that it belongs to. Therefore there is little practical purpose for exported functions to be used by a non-C++ program compared to exporting a non-C++ member function using extern "C". You can do it and it is more object-oriented to have the exported functions in their corresponding class but just understand that the most significant reason for doing that has very little advantage during execution.






Re: Visual C++ Language DLL questions with Visual Studio using C++

Mike Danes

You are correct about the "this"/member function stuff but note that Jason does not mention anywhere that he is using member functions. It seems that he is just using global overloaded functions



Re: Visual C++ Language DLL questions with Visual Studio using C++

einaros

 Simple Samples wrote:

One problem with exporting member functions for use by programs that are not written using C++ is "this". Every instance of a C++ class has a "this" pointer. Non-C++ programs, including C programs, don't know what the this pointer is and they don't know what a this pointer value is. When a C++ member (of a class) function is called, there is always a this pointer as the first parameter. You don't see it; C++ hides that parameter from us, but it is there. Unless the member function is a static member function.

While not very important to the task at hand, I just want to point out that the "first parameter" part isn't the full truth. This depends on the calling convention used to call the function.

A calling convention is simply the "cake recipe" which describes how the machine code for a function call is arranged. With native code in VC++, these conventions include

__stdcall

Parameters are pushed onto the stack starting with the last one (right-to-left), and the called functions cleans the stack when the function returns. When this convention is used for non-static member functions, the 'this' pointer is placed between the return address and the first parameter.

An example non-static member function may look like:

class Foo { public: void myFunction(int param1, char param2); };

For such a function, the stack will look like:

Return addr
This pointer
param1
param2
__cdecl This is the default calling conventions for non-member functions in VC++. As with __stdcall, parameters are passed from right to left, but unlike __stdcall; the calling function is responsible for doing the stack cleanup.
__fastcall

This calling convention will pass the two first parameters which are of size DWORD or less, in ECX and EDX registers respectively. The rest of the parameters will be passed right to left, and the called function cleans the stack (as with __stdcall).

For non-static member functions, the 'this' pointer will be passed in ECX (as with __thiscall). Since this means that ECX is taken, only one parameter (DWORD or smaller) will be passed in a register (EDX). The rest of the parameters will be passed on the stack.

__thiscall This is the default calling convention for member functions in VC++, and the convention is Microsoft specific. The 'this' pointer will be passed in ECX, and parameters are passed right-to-left. The called function will clean the stack.

 






Re: Visual C++ Language DLL questions with Visual Studio using C++

Simple Samples

Mike Danes wrote:
You are correct about the "this"/member function stuff but note that Jason does not mention anywhere that he is using member functions. It seems that he is just using global overloaded functions
Does Jason say anywhere that he is using global overloaded functions As far as I know, there is not such a thing as global overloaded functions, but I also admit that I don't know C++ well enough to be sure without checking the documentation. Regardless, I don't think that the question indicates that global overloaded functions are being used anymore than it indicates that member overloaded functions are used.

For me, "overloaded" implies member functions but not gloval functions.






Re: Visual C++ Language DLL questions with Visual Studio using C++

Simple Samples

Einaros, this is the first time I have seen anyone saying the "first parameter" part isn't the full truth. I know that you know the C++ language better than I so you could be correct.

Note that in the case of the __stdcall, there must always be a return address. The return address is not considered to be a parameter.

As you say, it does not matter much whether the this pointer is passed first or last. The important thing is that there is a this pointer for all non-static member functions, regardless of calling convention.

In the case of __fastcall, "one other parameter will be passed" is misleading; there can be multiple additional parameters, they are just passed on the stack.

In the case of the __cdecl calling convention, I am not sure where "after the last parameter on the stack" would be relative to the other parameters. The Bugslayer article in the 1998 MSJ has a table similar to the one you show but it just says that the __cdecl calling convention passes arguments right to left.






Re: Visual C++ Language DLL questions with Visual Studio using C++

einaros

Simple Samples wrote:

Einaros, this is the first time I have seen anyone saying the "first parameter" part isn't the full truth. I know that you know the C++ language better than I so you could be correct.

It's not that the "first parameter" concept is wrong -- my point is merely that I find it an oversimplification which may hide the other aspects of function calls.

Simple Samples wrote:

Note that in the case of the __stdcall, there must always be a return address. The return address is not considered to be a parameter.

And therein lies my point. Not all things put on the stack are parameters. All calls require a return address. This is a concequence of the call and ret instructions, and as such the convention.

Simple Samples wrote:

In the case of __fastcall, "one other parameter will be passed" is misleading; there can be multiple additional parameters, they are just passed on the stack.

In the case of the __cdecl calling convention, I am not sure where "after the last parameter on the stack" would be relative to the other parameters. The Bugslayer article in the 1998 MSJ has a table similar to the one you show but it just says that the __cdecl calling convention passes arguments right to left.

Poor wording on my behalf in both cases, thanks for pointing that out

One could also go as far as to claim that the calling conventions aren't the full truth. Depending on optimizations applied by the compiler, certain details may be ommitted entirely, and that's not just regarding inlining.






Re: Visual C++ Language DLL questions with Visual Studio using C++

Simple Samples

einaros wrote:
It's not that the "first parameter" concept is wrong -- my point is merely that I find it an oversimplification which may hide the other aspects of function calls.
Note that I did say that there are other things that C++ does that could be incompatible with other languages. I forget the exact words I use but I assume the exact words don't matter. The important thing is that I did indicate there is more but I did not make an effort to get the details. Your information about calling conventions does show that there are other potential incompatibilities.
einaros wrote:
And therein lies my point. Not all things put on the stack are parameters. All calls require a return address. This is a concequence of the call and ret instructions, and as such the convention.
It is much more than a calling convention; it is required by the definition of a function or subroutine. A call by definition must have a return address; otherwise it is a branch or goto or something such as that. Therefore a call (in compiled code at least) always has a return address passed to the called code, regardless of the compiler, and therfore the simple fact that there is a return address is insignificant.

einaros wrote:
One could also go as far as to claim that the calling conventions aren't the full truth. Depending on optimizations applied by the compiler, certain details may be ommitted entirely, and that's not just regarding inlining.
Could be. Hopefully that would not be relevant to mixed languages but it might be a potential problem.






Re: Visual C++ Language DLL questions with Visual Studio using C++

Mike Danes

Overloaded global functions are supported in C++. Event the CRT uses them (see fabs function for example).

"to code a DLL with some standard functions I use " is a pretty good indication that he is using just functions, not classes.





Re: Visual C++ Language DLL questions with Visual Studio using C++

Simple Samples

Mike Danes wrote:
"to code a DLL with some standard functions I use " is a pretty good indication that he is using just functions, not classes.
You could be right, but it would be better to hear from Jason.






Re: Visual C++ Language DLL questions with Visual Studio using C++

einaros

 Mike Danes wrote:

Overloaded global functions are supported in C++. Event the CRT uses them (see fabs function for example).

"to code a DLL with some standard functions I use " is a pretty good indication that he is using just functions, not classes.

This is another one of the orphaned threads, where the OP goes missing and everybody else keeps discussing what the solution is.

I feel pretty sure that Mike's first post pinned it, so I'm going to mark that one for now. If the OP returns, verify and unmark if necessary.






Re: Visual C++ Language DLL questions with Visual Studio using C++

Jason Wilborn

Sorry I asked a question and disappeared. The thread didn't get any answers for a while and I was checking daily. Then the holidays came and I switched positions at my job and time has been limited. I was surprised to see the topic had taken off in my absence.

As to some of the questions I would have to recompile my original test project where I got errors using the CLR. I'll have to do that when I have time.

At the moment I was starting small with DLLs and wanted only to code some overloaded functions. Eventually I have some classes I'd like to make into a DLL but I was starting with what I thought was simple.

I did read the documentation, but at times it confused me as my specific question never seemed to fit into the examples. I will try the suggestion about getting the mangled name and try again when I can sit down and code and will post my results.

Thanks for all the help from everyone.





Re: Visual C++ Language DLL questions with Visual Studio using C++

Jason Wilborn

Ok I've used the suggestions and I made some test DLLs and they exported their functions and I was able to import them into a Win32 project fine. I used export and import and used a .def file and both ways worked as long as i used a Win32 project. I got the basic setup and understood it.

Where I still run into problems is when I create a Windows Form Project. I follow the same steps for linking to the DLL but I get errors as it can't use __declspec(dllimport). From the help files I gather because Forms apps compile using CLR:Pure I can't import the usual way, but none of the examples seems to explain what you do to use the DLLs. I've tried .def files and I get the same thing. When I call the function I get this.

Linking...
WF_Test_App.obj : error LNK2028: unresolved token (0A00001D) "int __clrcall WF_Test_App::fnBasic_DLL(void)" ( fnBasic_DLL@WF_Test_App@@$$FYMHXZ) referenced in function "public: __clrcall WF_Test_App::Form1::Form1(void)" ( 0Form1@WF_Test_App@@$$FQ$AAM@XZ)
WF_Test_App.obj : error LNK2019: unresolved external symbol "int __clrcall WF_Test_App::fnBasic_DLL(void)" ( fnBasic_DLL@WF_Test_App@@$$FYMHXZ) referenced in function "public: __clrcall WF_Test_App::Form1::Form1(void)" ( 0Form1@WF_Test_App@@$$FQ$AAM@XZ)
C:\Code_VS\WF_Test_App\Debug\WF_Test_App.exe : fatal error LNK1120: 2 unresolved externals

The DLL side seems fine, but in a Windows Form project what should I be doing to correctly import in the functions from the DLL to make use of them

Thanks