0

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:

2
Contributors
13
Replies
14
Views
10 Years
Discussion Span
Last Post by WolfPack
0

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

0

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.

0

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

0

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.

Edited by Dani: Formatting fixed

0

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

0

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

0

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.

0

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

0

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.

1

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

Votes + Comments
Good effort.
This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.