Avatar of shaii
shaii asked on

Calling Function in Class from DLL

//I am trying to call the Open function
//in class NCDCtrl (NCDCtrl::Open) from
//VB

//I don't know how to declare it. At
//the beging I tried
extern "C"  int  _stdcall NCDCtrl::Open(char *);
//but I got at compilation:
//error C2027: use of undefined type 'NCDCtrl'

//here is the class
class NCDCtrl : public CommCtrl
{
public:
        NCDCtrl();
        virtual ~NCDCtrl();

// overidden to open the port and also syncronies it's baud rate with the NCD.
        BOOL Open(char *Com);
};

// after a little trying I tried this
extern "C" short _stdcall ShaiOpen(char *Com);

short _stdcall ShaiOpen(char *Com)
{
        short retVal = NCDCtrl::Open(Com);
        return (retVal);
}
//but when I compile the c++ project I
//get this error:
//error C2352: 'CommCtrl::Open' :
//illegal call of non-static member
//function


HELP!!!???
I want to know
1. Is it posible to run functions inside the class
2. If I need to rap them how???
C++

Avatar of undefined
Last Comment
shaii

8/22/2022 - Mon
nietod

You need to use __declspec(dllexport) to delcare the procedure so that it is exported from the DLL.  

continues.
nietod

When the DLL is compiled, you want to indicate the procedure should be exported, like

class NCDCtrl : public CommCtrl
{
public:
   NCDCtrl();
   virtual ~NCDCtrl();

   __declspec(dllexport) BOOL Open(char *Com);
};

However, when you are compiling somthing that uses the DLL, like an EXE or another DLL, you want to indicate that the procedure is imported so you would do

class NCDCtrl : public CommCtrl
{
public:
   NCDCtrl();
   virtual ~NCDCtrl();

   __declspec(dllimport) BOOL Open(char *Com);
};

If you want to use one definition for this class that aopears inside an include (.h) file, you can use the pre-processor to control whethor or not the procedure is imported or exported, like

#ifdef MyDll
#define MyDllExport __declspec(dllexport)
#else
#define MyDllExport __declspec(dllimport)
#endif

class NCDCtrl : public CommCtrl
{
public:
   NCDCtrl();
   virtual ~NCDCtrl();

   MyDllExport BOOL Open(char *Com);
};


Then inside your DLL's source code you would use

#define MyDll

before you include the .h file that cotains the class delcaration.

Not you would probably want to change the "MyDll" stuff above to reflect the name of your DLL.

Let me know if you have any questions
ASKER
shaii

Still problems,
  The compilation worked (as before) but I still don't know how to refrence the function from VB5

I tried this declaration:
Public Declare Function NCDOpen Lib "NMCommCtrl" Alias "Open" (ByVal Com As String) As Integer

but I get an error "can't find dll entry point"
I also tried in Alias "NCDCtrl::Open"
but same story

help!
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
nietod

You don't have to reject an answer if it seems incomplete or you can't understand it.  You can simply ask for clarification in a comment.  Most problems are solved through a dialog between the expert and the client.  But if you reject the answer another expert may come a long an lock the question onfairly, then they can get the points, rather than the expert that contributed the answer.
nietod

You're original question doesn't mention  VB. There are 2 problems here.  One is name C++ decoration, which can easily be solved.  The second is that VB doesn't support objects, that can't be solved, at least not simply.  

Can you explain what it is you are trying to do?  (in detail.)  Keep in mind that you are going to have to make a BIG change in HOW you get it done, so I need to know what the end goal is, not the way that you want to reach that goal.
ASKER
shaii

Ok here it comes.
I have a working DLL with all the functions I will ever need it is writen in VC++. but the problem as we know that till now they were working with the DLL with vc and now I come along and try calling the functions from VB and this is the problem.

I know that I can wrap it with COM (we did this for a different one)
is there any way of not doing so.

now the dll is big and has many class but one of them is NCDCtrl and a function in it in Open.
and I wanted to c if I can call it from VB.  I have no luck with that.  What I was able to do is make a newFunc in the Dll and call it from VB. At the begining I tried it with __declspec(dllexport)  but I don't think this is compolsory since it worked with _stdcall

that's all
Sorry for rejecting I don't have much experiance here ;
Shai
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
AlexVirochovsky

More probably, problem is in name of
function(becourse VC make some additions to origianal name, as _ or _8 ets..)
You must to know REAL name of function.
For this, I use
Borland tdump.exe Of course, there is
some utility in VC.(libdump.exe, if i don't wrong).
ASKER
shaii

I have no Idia what u are talking about.
plz be more ...
nietod

Alex, name decoration is A problem, but a small problem.  shaii is trying to call a non-static member function from VB, i.e. from a language that does not support objects.  That is a big problem.

>> I know that I can wrap it with COM
>> (we did this for a different one)
>> is there any way of not doing so.
That is one way of doing so, and if you have experience with this approach, it probably is the best way.

Another approach is to export "interface" functions from the VC DLL.  These would be non-member functions that take a pointer to an object as one of the parameters.  These functions can be called from VB because they are non-member functions.  Then inside those interface fucntions the code would use the pointer to call the member functions.  For this approach to work you would also have to export functions from the DLL that created the objects and returned a pointer to those objects and also export functions that destroy the object.   (This is because VB cannot create or destroy C++ objects directly, it would have to call a C++ function to do so for it.)  This might begin to sound a lot like using COM.  it is.

>> one of them is NCDCtrl and a function in
>>  it in Open.
>> and I wanted to c if I can call it from VB
But Open() is a non-static member function.  You must call it using a NCDCtrl object.  VB cannot create one of these objects, and even given one of these objects, it cannot call its non-static member functions.  VB can only call "regular" functions.

>> I tried it with __declspec(dllexport)  but I don't think
>> this is compolsory  
It is necesary if you want to export the function.  _stdcall is unrelated to this issue.   (i.e a function can be exported regardless of its calling convention.)  

>> since it worked with _stdcall
It didn't work.  VB can't possibly have made the call successfully.
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
ASKER
shaii

nietod,
 10x a million.
u helped me a lot.
So lets c if I understood u correctly
to call function NCDCtrl::Open I have to make an interface dll where I will have a destroctor for every object I use(CLASS?)
in this interface file I can put ShaiOpen (start comment) as is.

I have many functions so this may be usefull and I don't know how much work will it be to change it to ATL COM

I want to give u the points (if it's still posible) how?
10x again
Shai
ASKER CERTIFIED SOLUTION
nietod

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
See how we're fighting big data
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
nietod

If you don't use COM, then name decoration will be an issue.  Here is a description of name decoration I wrote earlier.  It discusses calling C++ from C, but the issue is the same as calling it from VB

************************
C++ "decorates" or "mangles" function names by appending a "code" to the end of the name that expresses the parameters passed to the function.  This is used to impliment function overloading, where 2 or more distinct functions have the same name and different parameters.  (Apparently they have the same name--C++ mangles the names so they don't actually have the same name).  

Ordinarily the C++ function is exported with the mangeled name.  C however doesn't do any name mangeling.  So when the C program tries to import the function it looks for the unmangled name.  So C cannot find the function written in C++.  

To fix this problem, you declare the function as "extern "C" ".  This dissables name mangeling on the function.

************************

There is another form of decoration to be dealt with too, that is standard call decoration.  But lets not worry about that yet, or ever ifyou will be using COM.
ASKER
shaii

I have tried to Implement what u have told me and added the "factory" functions.  Now my problem is to pass the class pointer to VB.
>>so just declare the pointer to be
>>some sort of "generic" pointer type
>>in vb, like a handle.
I looked up in VB help and found that I should set it as Long.

but when I try to run the constructor  VB crashes! and I get
"this program ... and will be closed"

I don't know if my error is in C or VB or both. Added is the C code and VB declaration :
extern "C" class NCDCtrl __declspec(dllexport) _stdcall CreateNCDCtrl();
extern "C" BOOL __declspec(dllexport) _stdcall DestroyNCDCtrl(class NCDCtrl *NCDptr);
extern "C" short __declspec(dllexport) _stdcall OpenNCDCtrl(class NCDCtrl *NCDptr,char *Com);

class NCDCtrl __declspec(dllexport) _stdcall CreateNCDCtrl()
{  
   return NCDCtrl::NCDCtrl();
}
BOOL __declspec(dllexport) _stdcall DestroyNCDCtrl(class NCDCtrl* NCDptr)
{
   delete NCDptr;
   return 1;
}
short __declspec(dllexport) _stdcall OpenNCDCtrl(class NCDCtrl* NCDptr,char *Com)
{
   short retVal = NCDptr->Open(Com);
   return (retVal);
}

//The VB DECLARATIONS
Public Declare Function CreateNCDCtrl Lib "NMCommCtrl" () As Long
Public Declare Function DestroyNCDCtrl Lib "NMCommCtrl" (NCDptr As Long) As Boolean
Public Declare Function NCDOpen Lib "NMCommCtrl" Alias "OpenNCDCtrl" (ByVal NCDptr As Long, ByVal Com As String) As Integer

Again thanx a lot
I don't know what would I do with out this help!

Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
nietod

This does not work.

class NCDCtrl __declspec(dllexport) _stdcall CreateNCDCtrl()
{
       return NCDCtrl::NCDCtrl();
}


you are passing a NCDCtrl _object_ to the caller.  That would be okay if the caller knew how to use an object, like a C++ program.  (But if that was the case, the caller could just create the object in the first place.)  VB can't work with objects, so it can't be passed an object.  You must pass it a pointer to an object.  It can work with the pointer, but it won't know what the pointer points to.  So all it can do with the pointer is save it and later pass it back to the C++ code at times.

So the factory function must create a new object _dynamically_ (the object must remain in existance until VB requests that it be destroyed) and it must return a _pointer_ to the object, like

class NCDCtrl * __declspec(dllexport) _stdcall CreateNCDCtrl()
{
       return  new NCDCtrl;
}
ASKER
shaii

nietod,
  I have done it! and it works  great!
thank u so much!!!
shai