   Loading Functions from a DLL
  Hi, I've been looking into using DLLs and calling functions from them, but I've hit a problem.  the tutorial i was usinghttp://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=6813&lngWId=3has a bug in it, or an oversight, or something, in any case it won't work properly.  The program can use a function from the DLL that takes no parameters with no issue, but a function with paramaters throws upDebug Error:"The value of ESP was not properly saved accross a function call.  This is usually the result of calling a function pointer declared with a different calling convention"i took that to mean that its expecting a return value, or i've messed up the parameters or something but from what i can see i've done everything right.compiled in visual c++ 6.0// Loader.cpp : Defines the entry point for the application.//#include "stdafx.h"#include "resource.h"#include &lt;windows.h&gt;#include &lt;stdio.h&gt;#include &lt;stdarg.h&gt;#include &lt;mmsystem.h&gt;#include &lt;string.h&gt;#define MAX_LOADSTRING 100// Global Variables:HINSTANCE hInst;// current instanceTCHAR szTitle[MAX_LOADSTRING];// The title bar textTCHAR szWindowClass[MAX_LOADSTRING];// The title bar text///////////////////////////////////////////////DLL STUFF/////////////////////////////////////////////Define DLL Callbacks (for the two functions we wrote in our DLL.//Because function 1 has no parameters, its void.  Function 2 takes char* as//a paramter so we put LPCSTRtypedef UINT (CALLBACK* LPFNDLLFUNC1)(VOID);typedef UINT (CALLBACK* LPFNDLLFUNC2)(LPCSTR);typedef UINT (CALLBACK* LPFNDLLFUNC3)(int);HINSTANCE hDLL;//Self explanitoryLPFNDLLFUNC1 MyFunc1;//Here we define variables for the callback functionsLPFNDLLFUNC2 MyFunc2;LPFNDLLFUNC2 MyFunc3;UINT  uReturnVal;char buffer[5];int variable = 0;// Foward declarations of functions included in this code module:ATOMMyRegisterClass(HINSTANCE hInstance);BOOLInitInstance(HINSTANCE, int);LRESULT CALLBACKWndProc(HWND, UINT, WPARAM, LPARAM);LRESULT CALLBACKAbout(HWND, UINT, WPARAM, LPARAM);int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTRlpCmdLine, int  nCmdShow){ // TODO: Place code here.MSG msg;HACCEL hAccelTable;// Initialize global stringsLoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);LoadString(hInstance, IDC_DLFOSHO, szWindowClass, MAX_LOADSTRING);MyRegisterClass(hInstance);// Load DLL into memory and store the pointer in hDLLhDLL = LoadLibrary("c:\\MyProject.dll");if (hDLL != NULL)//if the DLL loaded sucessfully{//Get the pointers to the functionsMyFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL,"MyDLLFunc1");MyFunc2 = (LPFNDLLFUNC2)GetProcAddress(hDLL,"MyDLLFunc2");MyFunc3 = (LPFNDLLFUNC2)GetProcAddress(hDLL,"MyDLLFunc3");//If either failsif (!MyFunc1 || !MyFunc2 || !MyFunc3){//Show error messageFreeLibrary(hDLL);  return false;}/*//Otherwise call themelse{uReturnVal = MyFunc1();uReturnVal = MyFunc2("HELLO WORLD!");}*/}// Perform application initialization:if (!InitInstance (hInstance, nCmdShow)) {return FALSE;}hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_DLFOSHO);// Main message loop:while (GetMessage(&msg, NULL, 0, 0)) {if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {TranslateMessage(&msg);DispatchMessage(&msg);}}return msg.wParam;}////  FUNCTION: MyRegisterClass()////  PURPOSE: Registers the window class.////  COMMENTS:////    This function and its usage is only necessary if you want this code//    to be compatible with Win32 systems prior to the 'RegisterClassEx'//    function that was added to Windows 95. It is important to call this function//    so that the application will get 'well formed' small icons associated//    with it.//ATOM MyRegisterClass(HINSTANCE hInstance){WNDCLASSEX wcex;wcex.cbSize = sizeof(WNDCLASSEX); wcex.style= CS_HREDRAW | CS_VREDRAW;wcex.lpfnWndProc= (WNDPROC)WndProc;wcex.cbClsExtra= 0;wcex.cbWndExtra= 0;wcex.hInstance= hInstance;wcex.hIcon= LoadIcon(hInstance, (LPCTSTR)IDI_DLFOSHO);wcex.hCursor= LoadCursor(NULL, IDC_ARROW);wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);wcex.lpszMenuName= (LPCSTR)IDC_DLFOSHO;wcex.lpszClassName= szWindowClass;wcex.hIconSm= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);return RegisterClassEx(&wcex);}////   FUNCTION: InitInstance(HANDLE, int)////   PURPOSE: Saves instance handle and creates main window////   COMMENTS:////   In this function, we save the instance handle in a global variable and//   create and display the main program window.//BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){   HWND hWnd;   hInst = hInstance; // Store instance handle in our global variable   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);   if (!hWnd)   { return FALSE;   }   ShowWindow(hWnd, nCmdShow);   UpdateWindow(hWnd);   return TRUE;}////  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)////  PURPOSE:  Processes messages for the main window.////  WM_COMMAND- process the application menu//  WM_PAINT- Paint the main window//  WM_DESTROY- post a quit message and return////LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){int wmId, wmEvent;PAINTSTRUCT ps;HDC hdc;TCHAR szHello[MAX_LOADSTRING];LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);switch (message) {case WM_COMMAND:wmId    = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections:switch (wmId){case IDM_ABOUT:   DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);   break;case IDM_EXIT:   DestroyWindow(hWnd);   break;default:   return DefWindowProc(hWnd, message, wParam, lParam);}break;case WM_KEYDOWN:  switch (wParam)   { case VK_SPACE: MyFunc1();break; case 'V':MyFunc2("ARGLEBARGLE");break;/*case 'B':variable = MyFunc3(variable);sprintf(buffer,"%d", variable);MessageBox(NULL, buffer, NULL, MB_OK);break;*/   }break;case WM_PAINT:hdc = BeginPaint(hWnd, &ps);// TODO: Add any drawing code here...RECT rt;GetClientRect(hWnd, &rt);DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);EndPaint(hWnd, &ps);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hWnd, message, wParam, lParam);   }   return 0;}// Mesage handler for about box.LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){switch (message){case WM_INITDIALOG:return TRUE;case WM_COMMAND:if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {EndDialog(hDlg, LOWORD(wParam));return TRUE;}break;}    return FALSE;}MyDll// MyProject.cpp : Defines the entry point for the DLL application.//#include "stdafx.h"BOOL APIENTRY DllMain( HANDLE hModule,    DWORD  ul_reason_for_call,    LPVOID lpReserved ){    return TRUE;}void MyDLLFunc1() {MessageBox(NULL,"My DLL Function 1","",MB_OK);}int MyDLLFunc2(char *TEXT) {MessageBox(NULL,TEXT,"",MB_OK);return true;} void MyDLLFunc3(int a){//return a++;}MyDll.defLIBRARY MyProjectDESCRIPTION This is my DLL file!EXPORTS    MyDLLFunc1@1MyDLLFunc2@2MyDLLFunc3  @3
  In the dll you are using the default calling (which is __cdecl) convention and in your applciation you're using the CALLBACK convention which is defined as __stdcall (??).Changing this:typedef UINT (CALLBACK* LPFNDLLFUNC1)(VOID);typedef UINT (CALLBACK* LPFNDLLFUNC2)(LPCSTR);typedef UINT (CALLBACK* LPFNDLLFUNC3)(int);to this:typedef UINT (*LPFNDLLFUNC1)(VOID);typedef UINT (*LPFNDLLFUNC2)(LPCSTR);typedef UINT (*LPFNDLLFUNC3)(int);Should do it.Read up on calling conventions: click;  [edit]Ah yea, and what IFooBar said about the calling conventionsThe first thing that I see is your function pointer definitions say:typedef UINT (CALLBACK* LPFNDLLFUNC1)(VOID);typedef UINT (CALLBACK* LPFNDLLFUNC2)(LPCSTR);typedef UINT (CALLBACK* LPFNDLLFUNC3)(int);But your actual functions are:void MyDLLFunc1();int MyDLLFunc2(char *TEXT);void MyDLLFunc3(int a);I think you need to fix that return type [wink]:typedef void (CALLBACK* LPFNDLLFUNC1)(VOID);typedef int (CALLBACK* LPFNDLLFUNC2)(char*);typedef void (CALLBACK* LPFNDLLFUNC3)(int);Also, you may need to 'export' your functions from the DLL:__declspec(dllimport) void MyDLLFunc1(){ ...}__declspec(dllimport) int MyDLLFunc2(char *TEXT){ ...}__declspec(dllimport) void MyDLLFunc3(int a){ ...}But I'm not sure if using the .DEF the way you are solves that.   ;  snipping the CALLBACK worked, thanks guys :D   