icode4food
asked on
Dealing with pointers calling into a C++ DLL from Visual Basic (VB6)
I have a C++ DLL formatted correctly to allow me to call into it from VB. The functions are declared in the module etc fine but the problem I am having is dealing with the pointers C++ uses.
One example with void* which is meant to be casted into a specific user defined type in C++.
void* deStateIn (int *size)
How can I handle this in VB? If I had a void* as a paramter how would I pass something into it from VB?
How do I deal with a pointer to a user defined object being returned?
diueStatusType* deCmdUpdateStatus()
How do I deal with a char* being returned?
char* deStateSite (int x, int y)
How do I deal with a method that takes a pointer to a unsigned char that is really a buffer for a string? (expecting something simliar to unsigned char ipaddr[16] = "000.000.000.000")
int diuInit (int max_slots, unsigned char*dest_ip, int udp_port)
Any help would be greatly appreciated. I have been trying to solve these issues for awhile and am not having any luck. Thanks in advance.
One example with void* which is meant to be casted into a specific user defined type in C++.
void* deStateIn (int *size)
How can I handle this in VB? If I had a void* as a paramter how would I pass something into it from VB?
How do I deal with a pointer to a user defined object being returned?
diueStatusType* deCmdUpdateStatus()
How do I deal with a char* being returned?
char* deStateSite (int x, int y)
How do I deal with a method that takes a pointer to a unsigned char that is really a buffer for a string? (expecting something simliar to unsigned char ipaddr[16] = "000.000.000.000")
int diuInit (int max_slots, unsigned char*dest_ip, int udp_port)
Any help would be greatly appreciated. I have been trying to solve these issues for awhile and am not having any luck. Thanks in advance.
ASKER
Thanks for the suggestions but
1) doesnt work. As Any cant be a return type on a DLL function declaration
2) I was told there is a way to get at the memory and overlay it but I havent had luck doing so.
3) doesnt work. if I wanted to assign "172.16.6.113" as the IP address I cant store it into a Byte array. An assignment that isnt a number into a Byte field does not work. Its a Type Mistmatch. Tried using CByte method as well and that won't work either.
4) see 3
1) doesnt work. As Any cant be a return type on a DLL function declaration
2) I was told there is a way to get at the memory and overlay it but I havent had luck doing so.
3) doesnt work. if I wanted to assign "172.16.6.113" as the IP address I cant store it into a Byte array. An assignment that isnt a number into a Byte field does not work. Its a Type Mistmatch. Tried using CByte method as well and that won't work either.
4) see 3
Just a char should correspond to a byte, and yes, you would want to return the ASCII value of that character into your byte. A char * should correspond to a byte array, with the same limitations I just mentioned.
Regarding the memory overlay, etc...it seems an awfully unorthodox method of working in the program. I would consider finding an ActiveX approach (the best way to work with objects between the two languages) or handle all class functions internally, using exported functions to allow VB to manipulate the properties and use the class.
If interested, this is the *proper* way to pass string to and from your dll to VB:
http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/Q187/9/12.asp&NoWebContent=1
Regarding the memory overlay, etc...it seems an awfully unorthodox method of working in the program. I would consider finding an ActiveX approach (the best way to work with objects between the two languages) or handle all class functions internally, using exported functions to allow VB to manipulate the properties and use the class.
If interested, this is the *proper* way to pass string to and from your dll to VB:
http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/Q187/9/12.asp&NoWebContent=1
ASKER
Was able to use Asc() to get the ascii value put into the byte. Whether the dll is able to handle this appropriately I can't tell yet without being able to resolve my other issues. I competely agree this program is "unorthodox" but the client keeps pushing for it even though I keep telling him I don't think its possible.
Can you use As Variant as a return type? What exactly are you trying to return? If its just a pointer, then As Long should do it.
What other issues are still outstanding?
What other issues are still outstanding?
ASKER
If I do it as a Variant return type and try to store it on return I get "Bad DLL calling convention."
Dim myVariant As Variant
myVariant = deStateIn(sizeRet)
deStateIn returns a void*. In normal use it is actually returning a pointer to a C++ user defined object, which is what I need to get at. If I did return the value as a long since its just a pointer then I need a way to dereference it like you would in C++ which is not an option in VB.
Dim myVariant As Variant
myVariant = deStateIn(sizeRet)
deStateIn returns a void*. In normal use it is actually returning a pointer to a C++ user defined object, which is what I need to get at. If I did return the value as a long since its just a pointer then I need a way to dereference it like you would in C++ which is not an option in VB.
You can do a trick to dereference an object pointer back into an object in VB, but VB must be aware of this object (e.g., be able to declare a variable of that type).
ASKER
I already have a type set up in VB to mimic the structure of the C++ type I am expecting. Its a rather long structure so I cut most of it, and due to security issues.
*** VB Code ***
Public Type pduEntityStateBaseType
version As Byte
exercise As Byte
type As Byte
protocol_family As Byte
time_stamp As Long
length As Integer
entitystate_pad2(2) As Byte
..
..
End Type
*** C++ Code ***
typedef struct {
UINT8 version;
UINT8 exercise;
UINT8 type;
UINT8 protocol_family;
UINT32 time_stamp;
UINT16 length;
UINT8 entitystate_pad2[2];
..
..
} pduEntityStateBaseType;
I know windows has a MSVBVM60.DLL which has calls such as GetMem4 which would get a long (32-bit) value at a supplied location.
' MSVBVM60.DLL functions
Public Declare Sub GetMem1 Lib "msvbvm60" (ByVal Addr As Long, RetVal As Byte)
Public Declare Sub GetMem2 Lib "msvbvm60" (ByVal Addr As Long, RetVal As Integer)
Public Declare Sub GetMem4 Lib "msvbvm60" (ByVal Addr As Long, RetVal As Long)
Public Declare Sub GetMem8 Lib "msvbvm60" (ByVal Addr As Long, RetVal As Currency)
Public Declare Sub PutMem1 Lib "msvbvm60" (ByVal Addr As Long, ByVal NewVal As Byte)
Public Declare Sub PutMem2 Lib "msvbvm60" (ByVal Addr As Long, ByVal NewVal As Integer)
Public Declare Sub PutMem4 Lib "msvbvm60" (ByVal Addr As Long, ByVal NewVal As Long)
Public Declare Sub PutMem8 Lib "msvbvm60" (ByVal Addr As Long, ByVal NewVal As Currency)
Dim vptr As Long
Dim newvalue As Long
' get the long (32-bit) (4-byte) value at the location (same as a C dereference of a pointer)
Call GetMem4(vptr, newvalue)
Problem is these gets arent able to get something large enough for the object I have. I was told to try using these get calls and overlay the information on the user defined object but I can't get that to work either.
*** VB Code ***
Public Type pduEntityStateBaseType
version As Byte
exercise As Byte
type As Byte
protocol_family As Byte
time_stamp As Long
length As Integer
entitystate_pad2(2) As Byte
..
..
End Type
*** C++ Code ***
typedef struct {
UINT8 version;
UINT8 exercise;
UINT8 type;
UINT8 protocol_family;
UINT32 time_stamp;
UINT16 length;
UINT8 entitystate_pad2[2];
..
..
} pduEntityStateBaseType;
I know windows has a MSVBVM60.DLL which has calls such as GetMem4 which would get a long (32-bit) value at a supplied location.
' MSVBVM60.DLL functions
Public Declare Sub GetMem1 Lib "msvbvm60" (ByVal Addr As Long, RetVal As Byte)
Public Declare Sub GetMem2 Lib "msvbvm60" (ByVal Addr As Long, RetVal As Integer)
Public Declare Sub GetMem4 Lib "msvbvm60" (ByVal Addr As Long, RetVal As Long)
Public Declare Sub GetMem8 Lib "msvbvm60" (ByVal Addr As Long, RetVal As Currency)
Public Declare Sub PutMem1 Lib "msvbvm60" (ByVal Addr As Long, ByVal NewVal As Byte)
Public Declare Sub PutMem2 Lib "msvbvm60" (ByVal Addr As Long, ByVal NewVal As Integer)
Public Declare Sub PutMem4 Lib "msvbvm60" (ByVal Addr As Long, ByVal NewVal As Long)
Public Declare Sub PutMem8 Lib "msvbvm60" (ByVal Addr As Long, ByVal NewVal As Currency)
Dim vptr As Long
Dim newvalue As Long
' get the long (32-bit) (4-byte) value at the location (same as a C dereference of a pointer)
Call GetMem4(vptr, newvalue)
Problem is these gets arent able to get something large enough for the object I have. I was told to try using these get calls and overlay the information on the user defined object but I can't get that to work either.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
For others that have to deal with pointers try this site. It gives good examples of using CopyMemory.
http://www.codeproject.com/vbscript/how_to_do_pointers_in_visual_basic.asp
http://www.codeproject.com/vbscript/how_to_do_pointers_in_visual_basic.asp
2) If you are talking about an internal class, I don't think you can pass pointers of it to and from VB unless it is an ActiveX object or a struct (user-defined type).
3) For char you would declare "As Byte" in VB
4) char pointer buffer for a string would be a byte array in VB, e.g., Declare SomeFunction Lib "mydll" (ByVal AVariable() As Byte)
I don't do any C++ programming so these are just speculated answers...