Hi to all, I'm new here, I start reading the forum and you have help me, now I heve the following problem, hope you can help me
Thanks.
Now my problem:
I want to write a DLL that returns an Object
I write a function in the DLL, that returns the object(this is an object I create, it has its header and cpp files), the DLL project compiles and I receive an DLL file

//--------------------------------------------------------------------------
MyObject GetMyObject() 
{    
    MyObject ObjectFromDLL();
    return ObjectFromDLL;
}
//--------------------------------------------------------------------------

I also, write in the DLL project a Def file with:

//--------------------------------------------------------------------------
LIBRARY    "ObjectDLL"

EXPORTS 
    GetMyObject @1
//--------------------------------------------------------------------------

* Until here, everytingh is OK, I think or I doing something wrong

An then comes the other project(exe, console) that uses the DLL, I did the following:
I define:

//--------------------------------------------------------------------------
typedef MyObject (CALLBACK* LPFNDLLFUNC1)(VOID);
HINSTANCE hDLL;              
LPFNDLLFUNC1 MyFunc1;
And then:
///Load DLL
hDLL = LoadLibrary("C:\\DLL\\ObecjtDLL.dll");
if (hDLL != NULL)
{
MyFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL,"GetMyObject");
    if (!MyFunc1)
        FreeLibrary(hDLL);       
    else
        MyObject test = MyFunc1();
}
//--------------------------------------------------------------------------

The console program compiles, but in the line "MyObject test = MyFunc1();", the program crashes, I receive the message:

//--------------------------------------------------------------------------
Debug Error!
Run-Timw Check Failure #0 - The value of ESP was not properly saved acrros a function call, This is usually a result of calling a function declared with one convention with a function pointer declared with different calling convetion.
//--------------------------------------------------------------------------

What I can do to makes this work, I really nedd your help, Thanks :eek:

Recommended Answers

All 13 Replies

Aren't you using the

extern "C" __declspec (dllexport)

wrappers?

No I'm not using dllexport, is this a must? I also write the function

int MyDLLFunc1() 
{    
    cout << "From DLL" <<endl;
    return 0;
}

without dllexport and works fine why a should use it, I'm new writing DLL, why I should use this, you also wirte warppers, what do you mean, thsnks

Post all your code. It will be easier to figure out what is happening using the whole code. The way a compiler builds a C++ function is different from how it builds a C Function. So when you are writing a DLL you have to tell the compiler to compile it as a C Function and not as a C++ function. Usually that is the reason for calling convention errors to occur. Anyway post all your code. Then it will be easier to explain.

Thanks this is the code I have the DLL project:
Operation.h

//-------------------------------------------------------------------------------

#ifndef OPERATION_H
#define OPERATION_H
#include <string>
#include <assert.h>
#include <iostream> 
class Operation
{
    protected:
        char *sname;
    public:
        Operation(char*);
        Operation();
        ~Operation();
        char* get_sname();    
        virtual int Operate() = 0;
};
#endif
//--------------------------------------------------------------------------------

Operation.cpp

#include "stdafx.h"
#include "Operation.h"
//-------------------------------------------------------------------------------
//Input: char* 
//Output: None
//Decription: Default Constructor
Operation::Operation(char *s_newname)
{    
    sname = new char[strlen(s_newname)+1];
    assert(sname!=0);
    strcpy(sname,s_newname);
    //sname =s_newname;
}
//--------------------------------------------------------------------------------
//Input: None 
//Output: None
//Decription: Default Constructor
Operation::Operation()
{
    strcpy(sname,"");
}
//--------------------------------------------------------------------------------
//Input: None 
//Output: None
//Decription: Default Destructor
Operation::~Operation()
{
    delete [] sname;
}
//--------------------------------------------------------------------------------
//Input: none
//Output: char
//Decription: Set name to the variable
char* Operation::get_sname()
//char * Operation::get_sname()
{
    return sname;
}
//--------------------------------------------------------------------------------

Div.h

#include "Operation.h"
using namespace std;

class Div:public Operation
{
    private:
        int x,y;
    public:
        Div(char *);
        Div();
        ~Div();
        void setName(char *);
        void setX(int);
        void setY(int);
        int getX();
        int getY();
        virtual int Operate();
        virtual void Ask_values_from_User();
};
//--------------------------------------------------------------------------------

Div.cpp

#include "stdafx.h"
#include "Div.h"
//-------------------------------------------------------------------------------
//Input: char*
//Output: None
//Decription: Default Constructor
Div::Div(char *s_newname):Operation(s_newname)
{
    x = 0;
    y = 0;
}
//--------------------------------------------------------------------------------
//Input: None 
//Output: None
//Decription: Default Constructor
Div::Div()
{
    x = 0;
    y = 0;
}
//--------------------------------------------------------------------------------
//Input: None 
//Output: None
//Decription: Default Destructor
Div::~Div()
{
}
//--------------------------------------------------------------------------------
//Input: char
//Output: None
//Decription: Set name
void Div::setName(char *s_newname)
{
    sname = s_newname;
}
//--------------------------------------------------------------------------------
//Input: int 
//Output: None
//Decription: Set variable X
void Div::setX(int _x)
{
    x = _x;
}
//--------------------------------------------------------------------------------
//Input: int 
//Output: None
//Decription: Set variable Y
void Div::setY(int _y)
{
    y = _y;
}
//--------------------------------------------------------------------------------
//Input: None 
//Output: int
//Decription: Get variable X
int Div::getX()
{
    return x;
}
//--------------------------------------------------------------------------------
//Input: None 
//Output: int
//Decription: Get variable Y
int Div::getY()
{
    return y;
}
//--------------------------------------------------------------------------------
//Input: None 
//Output: int
//Decription: operate Div
int Div::Operate()
{
    Ask_values_from_User();
        
        if( getY() == 0)
            return 0;
    
        return (getX() / getY());
}
//--------------------------------------------------------------------------------
//Input: None 
//Output: None
//Decription: Print input options to user
void Div::Ask_values_from_User()
{
    cout << "Please Enter two Numbers: ";
    cin >> x >> y;
}
//--------------------------------------------------------------------------------

DivDLL.cpp

// DivDLL.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"

#include "Div.h"

#ifdef _MANAGED
#pragma managed(push, off)
#endif

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    return TRUE;
}

Div GetDivObject() 
{    
    Div DllDiv("Div");
    cout << "From DLL" <<endl;
    return DllDiv;
}

#ifdef _MANAGED
#pragma managed(pop)
#endif
//-------------------------------------------------------------------------------

All the below was the DLL project
Now the Console Project:
//-------------------------------------------------------------------------------
Menu.h

#include "afx.h"
#include "Operation.h"
#include "Div.h"
using namespace std;
class Menu 
{
    private:
        int m_nSizeArray;
        int option;
        Operation **pOperations;
        bool m_bWasInit;
        static Menu* m_pInstance;
        Menu();
        ~Menu();
    public:
        static Menu* Instance();
        void PrintMenu();
        bool Init();
        void Start_Operate(int option);
        void Destroy_Singletone();
};
//-------------------------------------------------------------------------------

Menu.cpp

#include "stdafx.h"
#include "Menu.h"
//-------------------------------------------------------------------------------
//Working with DLL
#include <windows.h>
//typedef UINT (CALLBACK* LPFNDLLFUNC1)(VOID);
typedef Div (CALLBACK* LPFNDLLFUNC1)(VOID);
HINSTANCE hDLL;              
LPFNDLLFUNC1 MyFunc1;    
//-------------------------------------------------------------------------------
Menu* Menu::m_pInstance = NULL; // initialize pointer
//-------------------------------------------------------------------------------
//Input:None
//Output: Menu*
//Description: Create instance for the singleton class
Menu* Menu::Instance()
{
    if(m_pInstance == NULL)        //is it the first call?
        m_pInstance = new Menu; //create sole instance

    return m_pInstance;
}
//-------------------------------------------------------------------------------
//Input: None 
//Output: None
//Decription: Default Constructor
Menu::Menu()
{
    m_bWasInit = true;
    option = 0;
    m_nSizeArray = 0;
}
//-------------------------------------------------------------------------------
bool Menu::Init()
{        
      m_nSizeArray = 2;
      Operation*[m_nSizeArray];    
        
        for(int i=0; i<m_nSizeArray; i++)
        {
                if (i == 0)
                    pOperations [i] = new Sum("Sum");                   
               else
                    hDLL = LoadLibrary("C:\\DLL\\DivDLL.dll");
                        if (hDLL != NULL)
                        {
                            MyFunc1 =   (LPFNDLLFUNC1)GetProcAddress(hDLL,"GetDivObject");

                            if (!MyFunc1)
                                FreeLibrary(hDLL);       
                            else
                                Div test = MyFunc1();
                                //pOperations [i] = MyFunc1();
                        }            //################################################################
                else 
                    m_bWasInit = false;
        }
    
    return m_bWasInit;
}
//-------------------------------------------------------------------------------
void Menu::Destroy_Singletone()
{
    //Delete instance
    delete m_pInstance;
    m_pInstance = NULL;
}
//-------------------------------------------------------------------------------
//Input: None 
//Output: None
//Decription: Default Destructor
Menu::~Menu()
{
    //Delete the Objects
    for(int i=0; i<m_nSizeArray; i++)
    {
        delete pOperations[i];
        pOperations[i] = NULL;
    }

    delete [] pOperations;
}
//-------------------------------------------------------------------------------
//Input: char 
//Output: None
//Decription: Print menu for the user
void Menu::PrintMenu()
{    
    while( option != -1 )
    {
        cout << "----------------------------------" << std::endl;
        cout << "Choose an Operation to use" << std::endl;
            for(int i=0; i<m_nSizeArray ;i++)
            {    
                cout <<" "<< i << ". " << pOperations[i]->get_sname() <<std::endl;
            }
            cout << "-1. " << "Quit" <<endl;
        cout << "----------------------------------" << std::endl;
        cin >> option;
            if( option >= 0 && option < m_nSizeArray )
                Start_Operate(option);
            else
            {
                if( option != -1)
                    cout <<"Wrong Input, try again"<<endl;        
                            }
    }
}
//--------------------------------------------------------------------------------
//Input: None 
//Output: None
//Decription: Start all the Operates functions
void Menu::Start_Operate(int pi_nOption)
{
    cout << "Result: " << pOperations [pi_nOption]->Operate() <<std::endl;
}
///------------------------------------------------------------------------

I hope you can understand it, I hope I didn't miss coping something
Thanks

Isn't there a testing program to test this DLL? And what are these parts in Red? I get compile errors because of them.

Operation*[m_nSizeArray];

    for(int i=0; i<m_nSizeArray; i++)
    {
            if (i == 0)
                pOperations [i] = new [COLOR="Red"]Sum("Sum"); [/COLOR]  

Next time post your code inside CODE tags.

I didn't Post all the code, I have also a Class called "Sum", I was wandering can I upload the project, maybe will be easy?
The "Sum" class is very similar to the "Div" class the only diference is in the
Function:
int Sum::Operate()
{
Ask_values_from_User();

return (getX() + getY());
}
You don't have to use it.
Erase the lines:

if (i == 0) 
pOperations [i] = new Sum("Sum");

And the line
Operation*[m_nSizeArray];
should be:

pOperations = new Operation*[m_nSizeArray];

the
main is:

#include "stdafx.h"
#include "Menu.h"

int _tmain(int argc, _TCHAR* argv[])
{
	Menu *l_pSingletonMenu = Menu::Instance();

	if ( ! l_pSingletonMenu->Init() )
		cout << "Memory allocation failure!";
	else
		l_pSingletonMenu->PrintMenu();
	
	l_pSingletonMenu->Destroy_Singletone();

	return 0;
}

Thank you for your help

I'm attaching my solution, the after opening the zip file you will have two projects: MenuMng and DivDLL, you have to open the solution "MenuMng.sln", this include both projects.
Run the program and see that the program fails(in my program I load my DLL from "C:\DLL\DivDLL.dll", so you have to change the path,where your DLL is.
I hope you can help me
Thank you for your time
* By the way I'm uisng Visual Studio 2005

Try deleting

CALLBACK

from

typedef Div (CALLBACK * LPFNDLLFUNC1)(VOID);

. But I am not sure about returning an object from a DLL. All the DLLs I have written were using C. I will have to search on that further.

I delete it , but doesn't compile, I search the web, how to return objects form a DLL and I didn't found anything, is this possible at all, maybe I'm trying to do somethinhg that is not possible
Again Thanks

Well it compiled and ran for me. But there was a heap error after the distructor was called. The new line after you delete CALLBACK should be

typedef Div (* LPFNDLLFUNC1)(VOID);

I think it is possible to return a object from a DLL. Only I haven't done it.

You are rigth now I can compile it, but fail, thanks

First thank you for your help, if your are interested I found out how to return an object from a DLL
in the DLL file, we should return a pointer:

MyObject* GetDivObject()
{        
    MyObject *obj;
    MyObject = new MyObject();    
    return obj;
}

and in the Client program:

typedef MyObject* (CALLBACK* LPFNDLLFUNC1)(VOID);
HINSTANCE hDLL;              
LPFNDLLFUNC1 MyFunc1;

And then loading the DLL

commented: Good effort. +1

well done. Thanks for giving us all the answer. :idea:

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.