Calling Function in Class from DLL

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

//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
        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

I want to know
1. Is it posible to run functions inside the class
2. If I need to rap them how???
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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

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

class NCDCtrl : public CommCtrl
   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
   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)
#define MyDllExport __declspec(dllimport)

class NCDCtrl : public CommCtrl
   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
shaiiAuthor Commented:
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

Rowby Goren Makes an Impact on Screen and Online

Learn about longtime user Rowby Goren and his great contributions to the site. We explore his method for posing questions that are likely to yield a solution, and take a look at how his career transformed from a Hollywood writer to a website entrepreneur.

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.
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.
shaiiAuthor Commented:
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 ;
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).
shaiiAuthor Commented:
I have no Idia what u are talking about.
plz be more ...
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.
shaiiAuthor Commented:
 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
>> I have to make an interface dll
You could, but it is probably easier to make an interface function in the existing DLL.

>> where I will have a
>>destroctor for every object I use(CLASS?)
More than just that.  You will need:

1. a "factory" function for each class that needs to be used from VB.
  The function creates a new object of the class using "new" and then returns a pointer to the object created.  (VB can't "understand" the pointer returned, so just declare the pointer to be some sort of "generic" pointer type in VB, like a handle.)
2.  A "destructor" function  that takes a pointer to an object and deletes the object.  (Again the pointer declared on the VB side will be a "generic" pointer type.)
3.  For each member function you need to call in VB, you will need to declare an interface function.  The interface function takes the same parameters as the member function, plus one more, a pointer to the object to be used.  Again this will be a "generic" pointer in VB.  The interface function will use the pointer to call the object's member function.

To use this in VB, you call the factory function to create an object and get a pointer to it.  You save this pointer and then call 1 or more interface functions using this pointer and the other necessary parameters.  Finally, when you are done, you call the destructor function to delete the object.

>> 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
Both approaches will require lots of changes, but using COM might be easier if there are lots of classes and lots of functions to be called.   This is because you can make the necessary changes in C++ pretty easily and without much "thought".  If you were to use the other method, you will have to write all those interface procedures.  While they are simple procedures, there will be lots of them and it can take a long time to get them created.

>> I want to give u the points (if it's
>> still posible) how?
I have to answer.  After an answer is rejected, I don't answer unless requested.  (Also, when there is no answer pending, you can also accept a comment as an answer, this option is not available though when an answer is pending.)

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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.
shaiiAuthor Commented:
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);

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!

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;
shaiiAuthor Commented:
  I have done it! and it works  great!
thank u so much!!!
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.