Link to home
Start Free TrialLog in
Avatar of Dj_Fx8
Dj_Fx8

asked on

Help with first DLL

Hi

I have tried to create a DLL, so I Cereated MyDll using VS6 MFC AppWizard (dll)   type Regular DLL using shared MFC DLL

Now I want my DLL to contain this function
int fnTest(Cstring string)
{
  return string.GetLength();
}

Where and what do I need to do next??




Avatar of jkr
jkr
Flag of Germany image

>>Where and what do I need to do next??

You need to create a header file that applications that want to use the function in the DLL can include. Furthermore, you have to tell these apps that this function is imported from a DLL and tell the compiler linker to export this function from your DLL. This is done like

// test.h

#infdef TEST_DLL
#define DYNLINK __declspec(dllimport)
#else
#define DYNLINK __declspec(dllexport)
#endif

int DYNLINK fnTest(Cstring string);

Now, when building your DLL, all you have to do is

// test.cpp

#define TEST_DLL
#include <test.h>

Defining 'TEST_DLL' will make the compiler treat the function as 'exported', whereas an application that uses the header sees it as 'imported'.
Avatar of Dj_Fx8
Dj_Fx8

ASKER

>>>>#infdef TEST_DLL

Is that a typo and should be

#ifdef TEST_DLL


But now I'm getting the following error when I compile

D:\PROGRAMING\MyDll\MyDll.cpp(67) : warning C4273: 'fnTest' : inconsistent dll linkage.  dllexport assumed.
>>>>#infdef TEST_DLL
>>Is that a typo and should be
>>#ifdef TEST_DLL

No.
Ooops, yes, it should be

#ifndef TEST_DLL
#define DYNLINK __declspec(dllimport)
#else
#define DYNLINK __declspec(dllexport)
#endif

Avatar of Dj_Fx8

ASKER

Ok I've got the DLL to compile now and have created a Test App to test my dll function, but it won't compile. Now I have included the MyDll.lib in my test app as follows

#ifdef _DEBUG
#pragma comment(lib, "D:\\Programing\\MyDll\\Debug\\MyDll.lib")
#else
#pragma comment(lib, "D:\\Programing\\MyDll\\Release\\MyDll.lib")
#endif

#include "D:\\Programing\\MyDll\\MyDll.h"

and copied the dll to the test app source folder.

D:\PROGRAMING\Test\TestDlg.cpp(124) : error C2065: 'fnTest' : undeclared identifier
You also require the app to 'know' what the function fnTest is.  That is you require

#include "InsertPathToHeaderForFnTest"

in your app.


I use a generic 'export' header when I do a dll.  That has all the #includes for header files of functions the dll will export so I only require this one header to be included with the app.  Does that make sense?
A couple of other points.
Is this dll going to be used with C based apps?  (if yes you will also require extern "C" to prevent name mangling).
Is this dll going to be used with apps not coded in C/C++.  (If yes you will need to change the calling convention - settings, C/C++ settings, code generation to __stdcall)
>>D:\PROGRAMING\Test\TestDlg.cpp(124) : error C2065: 'fnTest' : undeclared identifier

How are you using it?
I think there is one minor mistake just
do the following in your dll project
press Alt + F7 to goto project settings
in c/c++ tab with category 'general'
add ,TEST_DLL to Preprocessor Definitions
or you can add following to

#define TEST_DLL in stdafx.h(if it is there or any header file that is included before test.h

//test.h

#ifndef TEST_DLL //here is mistake as TEST_DLL is not yet defined
#define DYNLINK __declspec(dllimport)
#pragma  message("dllimport")
#else
#define DYNLINK __declspec(dllexport)
#pragma  message("dllexport")
#endif

as you are defining TEST_DLL in dll project
when you compile see in output that "dllexport" is getting printed


Good luck
vijay

Avatar of Dj_Fx8

ASKER

vijay
>>>>>>#ifndef TEST_DLL //here is mistake as TEST_DLL is not yet defined

Does this not cover what you are saying

// test.cpp

#define TEST_DLL
#include <test.h>

Defining 'TEST_DLL' will make the compiler treat the function as 'exported', whereas an application that uses the header sees it as 'imported'.

jkr

>>>>>>How are you using it?

As follows in the CDialog::OnInitDialog();
  int n = fnTest();

Andy

>>>>>>#include "InsertPathToHeaderForFnTest"

I have the the header included

Still the same error msg.

Can I just run over what I have done in the DLL because I'm not sure if I have declaration and definition in the correct places

I created the dll as I said in my orginal post which in the class view gave me

MyDllClasses
       CMyDllApp()

So I declared my function in MyDll.h, and defined it in MyDll.cpp

Is that ok


Now I have used a DLL Spyer and it shows 1 function in my dll
   ?fnTest@CMyDllApp@@QAEHXZ             Mem Id No  268439557


If thats any help
>>>>>>How are you using it?
>>As follows in the CDialog::OnInitDialog();
>>  int n = fnTest();

Hm, your exported function is/was

int fnTest(Cstring string)
{
  return string.GetLength();
}

So, you should use it like

CString str("test");
int n = fnTest(str);

When you do not supply an argument, the function will fail to find the function.

Thats a decorated name.  

Just try this out

#ifndef TEST_DLL
#define DYNLINK extern "C"  int __declspec(dllimport)
#else
#define DYNLINK extern "C"  int __declspec(dllexport)
#endif

so the names aren't decorated.  (I've just copied the define from an earlier post, hope no spelling mistakes).
NOTE I have also put the return type of function before the __declspec
>> extern "C"  

You think that's a good idea with a function that takes an object as the argument?
If it doesn't like the CString you may have to use

int FnTest(LPCTSTR pszSomeString)
{
return _tcslen(pszSomeString);
}
jkr.
I am trying to see if it works overall with a slightly different way of defining the function.  It's obvious this is a test function, maybe a CString object isn't really required.
>>If it doesn't like the CString

This is the MFC area :o)
Avatar of Dj_Fx8

ASKER

Sorry jkr I had simplified the function when I was having problems, it simply is the following at the min
int fnTest()
{
   return 50;
}
>>Sorry jkr I had simplified the function when I was having problems

Have you changed the header file also?
Avatar of Dj_Fx8

ASKER

Ok I might be onto something

#ifdef _DEBUG
#pragma comment(lib, "D:\\Programing\\MyDll\\Debug\\MyDll.lib")
#else
#pragma comment(lib, "D:\\Programing\\MyDll\\Release\\MyDll.lib")
#endif

When I changed to Release for my test app it just gave me the same error.... I don't have a Release version of the dll done yet, should I not have got an error saying the dll was missing ???

Avatar of Dj_Fx8

ASKER

>>>Have you changed the header file also?

Yip
Avatar of Dj_Fx8

ASKER

Sorry I missed a few posts
I tried the extern "C"

This line     #define DYNLINK   extern "C"  int __declspec(dllexport)

caused the following errors
Compiling...
MyDll.cpp
dllexport
d:\programing\mydll\mydll.h(38) : error C2059: syntax error : 'string'
d:\programing\mydll\mydll.h(38) : error C2238: unexpected token(s) preceding ';'
D:\PROGRAMING\MyDll\MyDll.cpp(66) : error C2039: 'fnTest' : is not a member of 'CMyDllApp'

mydll.h(38)
int DYNLINK fnTest();

mydll.cpp(66)
int CMyDllApp::fnTest()


>>NOTE I have also put the return type of function before the __declspec
What happens whent I add other functions with diferent return types
As I put "#pragma message" so you can see it yourself that if exported part is included or import part, just check it out and let me know.

Because when I put your code in test program(dll) it shows me warning that it is getting function imported instead of exported (hence the error function not defined in test program using the dll)so I put it in project setting and it is working.


putting #define TEST_DLL in your main file will not affect test.h so better put it the place I told you to.

Vijay
Edit the .def file of the dll and put in

EXPORTS
    ; Explicit exports can go here
      FnTest


in theory not necessary but..
ASKER CERTIFIED SOLUTION
Avatar of vijay_visana
vijay_visana

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Dj_Fx8

ASKER

Hi Vijay

>>As I put "#pragma message" so you can see it yourself that if exported part is included or import part

I put them in as you said and when I compile the DLL I get dllexport, and dllimportwhen I compile the Test app

>>ok tell me one thing what  is CMyDllApp?

VS wizard put it there when I created the project for making the  DLL


>>I think we are making very simple concept confused for nothing.

Yes we are, as is often said, can't see the trees for looking at the forest. The whole problem has been because I had declared fnTest as a member of CMyDll class, I simplified it as you suggested and it worked.

I would like to thank all 3 of you for helping me out and no doubt I'll be calling again on your skills and knowledge again in the near future. I feel that vijay should get the points as it was his post that lead me to the discovery of my problem, but I also feel andy and jrk deserve points too, so I will put up a question titled Andy And Jrk, so if you guys post to it I see you get a little something for your effort here

Many may thanks to all

Steven

No thanks for not honoring our efforts :-(

Will keep that in mind when deciding whether to post to your next Q or not.
Avatar of Dj_Fx8

ASKER

jkr

>>No thanks for not honoring our efforts :-(

>>Will keep that in mind when deciding whether to post to your next Q or not.

PLEASE re-read my last post, you and andy will be honored
*ARGH* - sorry, maybe I should not post anywhere when I really am p***ed from doing household chores the whole day. My apologies....
Avatar of Dj_Fx8

ASKER

Oh don't worry about it, I understand where your coming from, I just felt 500pts between the 3 of you's wasn't enough
Any way thank all of you?
Jkr it is good gesture from you that u realize immediately.
Any way I think we are here to share our knowledge, the knowledge we haven't born with  but learn from someone else so it is our duty to keep this chain alive. See I think points are just for keep our ego high and keep us motivated so we should take it positively

Vijay