Solved

Basics for setting up a C++ DLL for VB

Posted on 1998-01-23
16
271 Views
Last Modified: 2012-05-04
I've been trying to call a C function from a VB project, but keep getting a run-time error '453': Can't find DLL entry point for <function> in <path>.

I've set up the VB side and called the Windows API MessageBeep() and it works great.  I think I'm just missing something in my function declaration or something else. I just need to know what are the essential tasks in making a function visible to a VB project. (i.e. declarations, return types, includes, etc.)
0
Comment
Question by:kodiak1
  • 8
  • 8
16 Comments
 

Author Comment

by:kodiak1
ID: 1178755
Edited text of question
0
 
LVL 22

Accepted Solution

by:
nietod earned 70 total points
ID: 1178756
answer coming.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1178757
Here is a sample VC C++ dll that exports a single function.  To export a finction you need to declare it with __declspec(dllexport), since that is ugly, I #define DllExp.  Since you will be exporting to an non C++ application you need to use the extern "C" directive to tell it not mangle the function name.  (You could use a #define to put the extern "c" in as well, I don't.)

#define DllExp __declspec(dllexport)

DllExp extern "C" int FunctionToExport(int i)
{
   return i + 1;
}

bool
WINAPI DllMain(HINSTANCE DLLHnd, // >> DLL module.                              ULONG     Rsn,    // Reason for calling fuction.                 LPVOID    Rsv)    // Reserved.                    {
   return true;
}

0
Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

 
LVL 22

Expert Comment

by:nietod
ID: 1178758
Wow that came out really badly formatted!

here is the DllMain again.

bool
WINAPI DllMain(HINSTANCE DLLHnd,ULONG Rsn,LPVOID Rsv)
{
   return true;
}
0
 

Author Comment

by:kodiak1
ID: 1178759
Now I seen the declaration part before, however, I have no idea what the dllMain function is for.  I'm assuming that it is the entry part of the file I was missing before.  Is this needed in every DLL file? Could you give me some reasoning behind the DLLMAIN function?
0
 
LVL 22

Expert Comment

by:nietod
ID: 1178760
Every dll, just like every EXE, must have a an entry point.  The entry point is specified to the linker which records its location in the dll file, so the entry point could be called anything you want.  However, for convenience, Visual C treats any procedure with the name "DllMain" and the appropriate arguments as the entry point.  (Strictkly speaking it is not the entry point.  The VC run-tim libraries contain the entry point which then calls this procedure.)

This procedure is required for all Dll's.  Windows will call the procedure under 4 circumstances.  When the library is attached to a process, detached from a process, attached to a thread, detached from a thread.  The Rsn parameter indicates why the procedure is being called.  The bool return value is used only when attachiong to a process.  If the procedure returns false, it indicates the Dll could not initialize for some reason and windows will not continue to start up the EXE or DLL that uses the Dll.  

If you do not have to do any start-up/shut-down processing, you can leave the procedure blank, as I did in the example.
0
 

Author Comment

by:kodiak1
ID: 1178761
I'm sure I'm doing something really stupid, but I think I'm missing an include file or library.  It doesn't like the DllMain declaration The error I keep getting is:

error C2239: unexpected token 'identifier' following declaration of 'WINAPI'
 
  and also

error C2061: syntax error : identifier 'DllMain'

Do I use another name, is DllMain something you came up with?  Here's exactly what I have in .cpp the file.:

#define DllExp __declspec(dllexport)

DllExp extern "C" int Myfunc(int i)
{
        return i + 1;
}

bool WINAPI DllMain(HINSTANCE DLLHnd,ULONG Rsn,LPVOID Rsv)
{
return true;
}

Do I need a include to declare WINAPI as a keyword?  Thanks for al the extra effort.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1178762
you need to include the windows include files "windows.h".  I have to go.  hopefully this helps you.  I'll check in tomorrow morning.
0
 

Author Comment

by:kodiak1
ID: 1178763
I'm still having trouble seeing these functions in VB.  I have recently added the name to the .Def file and it finally worked, but it died once it was passed through the function.  Now I can't get it to work again.  Did it not unload the DLL correctly?  do I need to do something specific to keep it from doing that?  I think this is bigger than I thought to begin with.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1178764
I suspect the problem now is calling syntax, that is parameter format and/or order.  

The default C++ calling convention (__cdecl) is to place parameters on the stack in reverse order and the caller is responsible for removing the parameters after the function returns.  Return values are returned in EAX.  Does this match the VB calling convention and/or can you specify that this convention be used for a function.  

Vissual C also supports the pascal (__stdcall) calling convention.  In this case the function is responsible for cleaning up the stack.  

If this doesn't help, post some sample code.


0
 

Author Comment

by:kodiak1
ID: 1178765
BOOL WINAPI DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason,
                 LPVOID lpReserved )
                 {
                     switch( fdwReason )
                     {
                     case DLL_PROCESS_ATTACH:
                     break;

                     case DLL_THREAD_ATTACH:
                     break;

                     case DLL_THREAD_DETACH:
                     break;

                     case DLL_PROCESS_DETACH:
                     break;
                     }
                     return FALSE;
                 }

__declspec( dllexport ) int WINAPI DateAndTime( int i )
{
      
      return i + 2;

}

The above is my C++ exported function.  I had it returning i + 1 and no matter what I passed in I got -3513 and now I get -3512.  On the VB side this is how I declared it:

Option Explicit

Declare Function DateAndTime Lib "Framer" (i As Integer) As Integer

the function name doesn't mean anything, I'm just trying to get stuff to work.  Its not crashing, but I'm not sure why its working? Or why its giving screwy numbers.  You'll have to tell me if you think its a VB problem.  I'm not sure now.  I had no trouble calling pre-compiled WINAPI functions before.  thanks
0
 

Author Comment

by:kodiak1
ID: 1178766
Finally got this to work thanks for your efforts.  I just changed the (i As Integer) As Integer to (ByVal i As Integer) As Integer and changed the declaration of the C to short instead of integer.  thanks for you help
0
 
LVL 22

Expert Comment

by:nietod
ID: 1178767
A short is only 16 bits.  Is that the right size?
0
 

Author Comment

by:kodiak1
ID: 1178768
I can change that as the data deems it necessary.  I just needed something to work.  I'm in a kind of demonstration phase and needed a working system.  I'll switch to longs if I need bigger numbers.  

I may have to implement array or string passing and I'm not too sure how I'll do that, but I'll worry about that bridge when I come, unless its a no brainer.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1178769
I understand that.  My question was does a VB integer correspond to a C++ short?  i.e. is a VB integer only 16 bits.  (I'm not looking for an answer, I just want to make sure that's a question you've asked yourself.)  
0
 

Author Comment

by:kodiak1
ID: 1178770
Sorry, I misunderstood.  I'm not sure, but from other materials I've read it seemed to suggest just that.  

   short = integer
   long = long
   double = double
0

Featured Post

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

776 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question