|
-
Sep 9th, 2001, 07:35 AM
#1
Thread Starter
PowerPoster
passing structure from VC DLL to VB through CALLBACK function
Hi! I need some help...
I've successful wrote my DLL in VC with CALLBACK function support. But now I need to return a group of data in a form of structure from VC to VB.
Does anyone know how to work out this? For your info, I manage to return a string, long & others data type but not the structure.
regards,
-
Sep 9th, 2001, 09:19 AM
#2
Did you try --
Pass the struct from VB to the dll ByRef.
Treat the incoming data in the dll code as a pointer to a struct.
Parameters to C functions are by default passed by value.
-
Sep 9th, 2001, 11:46 AM
#3
Thread Starter
PowerPoster
jim mcnamara, the method you mention is working and I did it before.
But now... Im develop a GPS and GSM modem driver. hence, I can not do it that way. "coz I don't wish to have a polling from external by passing the structure into the DLL. But, what I want to do is a auto CALLBACK from the DLL.
Since, both the GPS and GSM driver will have a CommWatchProc thread function within it to read the incoming data from the serial port. So after inteprete this data and store into a predefine structure, then all the driver need to do is call an external program function through the CALLBACK method (the given address of the CALLBACK function upon the DLL is loaded) and return either GPS or GSM structure to this external program as
part of the arguement of this CALLBACK function.
Hope, you get what I mean. Upto this stage, I manage to return the long, double data type from VC (DLL) to VB program but not yet VC (DLL) to VC Program.
Once, I solve everything, I'll post the sample code to here and my home page. As this is the most frequent ask question 
Does, any one have more guideline, hints, tips? Hope I can resolve this soon 
regards,
Last edited by Chris; Sep 9th, 2001 at 11:50 AM.
-
Sep 9th, 2001, 08:13 PM
#4
Thread Starter
PowerPoster
Hi, Finally can manage to partially solve the passing structure from the DLL to my external program. But I still facing a problem and I have somethings which I not really clear about it and hope someone can explain a little bit more detail to me 
Here is my VC DLL Definition file:
; MyDLL.def : Declares the module parameters.
LIBRARY "MyDLL.dll"
EXPORTS
MyMultiply @1 ;PRIVATE
MyLTrim @2 ;PRIVATE MyRTrim @3 ;PRIVATE
MyCallback1 @4 ;PRIVATE
MyCallback2a @5 ;PRIVATE
MyCallback2b @6 ;PRIVATE
MyCallback2_SetProcAddress @7 ;PRIVATE
MyTimerProc_Start @8 ;PRIVATE
MyTimerProc_Stop @9 ;PRIVATE
Q1. Does the @x important?
-----Where x equal to total memory size require.
-----As from the MSDN, I know this is use to indicate the total memory in byte require for that particular function (for both input arguement and output result).
Q2. How about the PRIVATE keyword behind it?
Incident 1
With the PRIVATE at the end of the EXPORT list.
E.g.
MyCallback1 @4 PRIVATE
-----When I compile the DLL and test with the normal WIN32 VC application. I hit the Unresolved External link error (LINK 2001).
-----But there is no error in VB test program. Why?
Incident 2
Without the PRIVATE at the end of the EXPORT list.
E.g.
MyCallback1 @4
-----There was no link error in VC test program.
-----But When ran the VB test program, will hit the following error. ('DLL entry poiint for MyCallback1 not found'). Why?
Q3. Does the __cdecl equal CALLBACK keyword?
E.g.
typedef void (__cdecl* ExCallback1)(long);
and
typedef void (CALLBACK* ExTimerProc)(long);
Q4. Does CALLBACK function must return a value?
E.g.
If define as:
__declspec(dllexport) void __stdcall MyCallback2(long lParam1, char *strParam2)
----The lParam1 and strParam2 will not equal to the pass in value.
If define as:
__declspec(dllexport) long __stdcall MyCallback2(long lParam1, char *strParam2)
-----The lParam1 and strParam2 will equal to the pass in value.
Q5. Why I hit 'Unhandle error' in my VB callback function upon I execute any standard window API function like 'GetTickCount'?
Q6. Why I can't use 'On Error' in my own define callback function?
E.g.
VB Code:
Sub Callback1 (Byval lParam1 As Long, Byval lParam2 As long)
On Error Goto Errhandle:
' All my code is here...
Exit Sub
ErrHandle:
End Sub
Q7. I manage to return the structure to my VB main program.
Let said, my structure is having 2 parameters:
E.g.
VB Code:
Public Type CB2
ID As Long
Name As String * 255
Type
Public pv1 As CB2
When the callback function is fire, I received this structure and all the data inside this function is correct except the String parameter. Where I get the question mark and not my data.
But when I check with my VC DLL (1 step before calling this callback function and all the data inside this structure is perfectly assign/copy). What cause the problem? Do I need some special syntax to handle this string passing?
Again, I hit 'ESP' error in VC test program too.
I've enclosed the saource for the DLL (VC) and two (2) test program in both VC and VB.
Q8. Whats the different between the 'WINAPI' and __declspec(dllexport) void __stdcall?
I really appreatiate someone can guide me to a correct direction on creating a cross language DLL or a perfect driver 
The sample code is available at this URL... MyDLL.zip
regards,
Chris
Last edited by Chris; Sep 9th, 2001 at 10:51 PM.
-
Sep 10th, 2001, 05:52 AM
#5
Monday Morning Lunatic
1. You don't need it. You can get away with:
Code:
LIBRARY "MyDLL.dll"
EXPORTS
MyMultiply
MyLTrim
; ...etc...
It doesn't equal the amount of memory required, that is part of the internal function name.
2. I never used PRIVATE 
3. CALLBACK == __stdcall
4. No, you don't have to return a value. However if you don't the VB definition must be Sub, otherwise Function.
5. "Unhandle error"? Where is the error coming from? VB? Windows?
6. Don't know - not done VB for ages.
7. Are you passing the structure to the DLL and changing it there, or passing it from the DLL to the VB program?
8. WINAPI == CALLBACK == __stdcall. It just defines how the function is called (for example conventions on passing parameters, who's responsible for cleaning up, things like that. __declspec(dllexport) is VC++ specific and is a lot more useful if you're only using DLLs between VC++ code (you don't need a .DEF file, but it won't work with VB).
I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You".
-- Linus Torvalds
-
Sep 10th, 2001, 07:30 AM
#6
Thread Starter
PowerPoster
thx parksie. as for...
Q5. The error is from VB.
Q7, I pass the structure from DLL to VB/VC external program.
Q8. That mean if the DLL is compile for VB used, than I need the DEF file?
regards,
-
Sep 10th, 2001, 07:38 AM
#7
On another, but related note, I have a template class defined in my DLL. Can I use it in VB (painlessly)?
Z.
-
Sep 10th, 2001, 07:48 AM
#8
Zaei: I don't think VB supports template classes. But since templates are replaced by real classes/functions at compile time, you should be able to use a specific version in VB:
PHP Code:
template <class T> class SimpleT
{
T value;
};
SimpleT<int> obj;
you could use
Code:
private type SimpleTLong 'or whatever
Long value;
end type
Chris: Sorry, I can't help you with this
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Sep 10th, 2001, 07:52 AM
#9
Thread Starter
PowerPoster
it okay... thx cornedBee
-
Sep 10th, 2001, 07:59 AM
#10
Monday Morning Lunatic
Originally posted by Chris
thx parksie. as for...
Q5. The error is from VB.
Q7, I pass the structure from DLL to VB/VC external program.
Q8. That mean if the DLL is compile for VB used, than I need the DEF file?
regards,
5 & 6 - No idea, sorry.
8 - Yes, you'll need it unless you're compiling as C code and don't mind using the _func@size notation.
I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You".
-- Linus Torvalds
-
Sep 10th, 2001, 08:02 AM
#11
Thread Starter
PowerPoster
How to use the _func@size notation ? Can I have some sample code?
-
Sep 10th, 2001, 08:10 AM
#12
Monday Morning Lunatic
Okay. If you're compiling as C++, you need to use prototypes like this:
Code:
extern "C" void WINAPI function(int param, short other);
This would be decorated as _function@6 for (4+2) bytes.
I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You".
-- Linus Torvalds
-
Sep 10th, 2001, 08:11 AM
#13
Thread Starter
PowerPoster
ic.... how about if I compile with VC++ 6.0?
-
Sep 10th, 2001, 08:15 AM
#14
Monday Morning Lunatic
Same thing happens
I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You".
-- Linus Torvalds
-
Sep 10th, 2001, 07:48 PM
#15
Thread Starter
PowerPoster
parksie, thx a lot for your guideline & advice 
last nite I manage to resolve the passing structure from MyDLL.dll to the external VC++ program.
To resolve this I have change my structure from the original to below:
PHP Code:
// From this...
typedef struct tagCB2
{
long ID;
char Name[256];
} CB2, FAR *LPCB2;
// To below...
typedef struct tagCB2
{
long ID;
char *Name;
} CB2, FAR *LPCB2;
but... ... ...
I still can not resolve the corrupted string value when passing the structure from MyDLL.dll to external VB program. Where I have modified the VB UDTs too
VB Code:
'// From this...
Public Type CB2
ID As Long
Name As String * 256
End Type
Public pv1 As CB2
'// To this...
Public Type CB2
ID As Long
Name As String
End Type
Public pv1 As CB2
After I search from MSDN, I found something about the string pointer in VB StrPtr function. But does seme one know how to convert this string pointer back to the normal string and store in a string variable in VB?
I try to used the CopyMemory API to put this memory block of data into a Byte array, yet can't resolve my problem.
Hope someone can post more tips 
By the way, I juz uplodaed the new source code mydll.zip at the same URL in my previous post.
regards,
-
Sep 11th, 2001, 07:05 AM
#16
Thanks CornedBee. I KNOW templates aren't supported in VB, but your suggestion should work. Thanks.
Z.
-
Sep 17th, 2001, 11:06 PM
#17
Thread Starter
PowerPoster
yeah... finally I manage to work out how to return a string from VC++ DLL to VB program by using the Basic STRing (BSTR). But... I still unable to resolve the return string from VC++ DLL to VB as the member of the return structure 
The full sample code + doc is now available at my homepage (concept) section feel free to download and comment it.
By the way, I have a question here.
Since, I compile a dll and I get the following item:
1. MyDLL.lib
2. MyDLL.dll
Usually, we include the MyDLL.lib into Project|Settings|Link under the Object/Library section
Then juz declare the necessary function as following in the cpp file:
PHP Code:
__declspec(dllimport) long __stdcall MyRTrim(char *strSource, char *strBuffer, long lBuffSize);
__declspec(dllimport) long __stdcall MyCallback1(long lAddress, long lInput);
So, my question is, can I include the MyDLL.h instead of the MyDLL.lib library file? Although this sound to be a stupid question, but hope someone can answer it 
regards,
-
Sep 18th, 2001, 01:32 AM
#18
Fanatic Member
Hey Chris, I am trying to do the same thing and cantr get it to even run in vb without giving me the ever famous "VB has performed an Illigal Opperation - Close". Do you think you can help?? anyone??
Anyways, getting back to your post, a template class "WILL NOT" be compiled UNLESS you instanciate an instance of that type... for example:
if you have a template class and dont refer to it, it would be as if you havent had one to begin with.
ALso if you have a template class and you instanciate an "int" instance, you CANNOT USE IT for any other type. So in theory, all you have to do in your code is:
template <class T> class SimpleT
{
T value;
};
... then somewhere in your int main() or dllentry, you do:
SimpleT<int> i;
SimpleT<long> l;
SimpleT<char> c;
SimpleT<float> f;
SimpeT<double> d;
...
to compile int,long,char,float,and double instances of the template class.
Now back to my question:
I have already asked the question a while back... but no response!
http://www.vbforums.com/showthread.p...hreadid=103919
-
Sep 18th, 2001, 07:13 AM
#19
Chris:
You must always include the .lib file. You can, if you want, write a header file that declares the dll functions, just for external use. You can also use a common header for both the DLL and it's users, but this is more comlpicated. Basically you declare two macros:
#define DLLCOMPILE
this is only defined when you compile the dll, in the compiler options. ( /d "DLLCOMPILE")
#define DLLAPI
this will replace _declspec(dllexport) in the header file, it is defined as follows:
#ifdef DLLCOMPILE // the dll is compiled
#define DLLAPI _declspec(dllexport)
#else // the header is included by a program that uses the dll
#define DLLAPI _declspec(dllimport)
#endif
Now you can use one header file for both usages, and you don't even need a .def file.
Note that you NEED a def file if you want to use the dll with VB, you also shouldn't use the dllexport then (though I don't know if it hurts).
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Sep 18th, 2001, 07:31 AM
#20
Thread Starter
PowerPoster
Thx, CornedBee. yap my DLL is going to use by VB and VC++ program at the sample time.
if I declare my function using the standard calling convention like
_declspec(dllexport), do I still need to declare this function in my header file? For instance, I did not do this and I just declare once only when I create a function.
And you said that I must include the lib file allthe time when a third part program intend to use this dll. But how about if i load this DLL using the LoadLibrary, GetProcAddress and FreeLibrary API call, do I still need the lib file?
For this situation, I know that i can not use the standard calling cenvention when i plan to use the LoadLibrary API function at runtime.
regards
-
Sep 18th, 2001, 08:39 AM
#21
1) Yes you do. The _declspec(dllexport) is a help for the linker, the function prototype for the compiler.
2) You can use LoadDll and GetProcAddress instead of using the lib, but it's a damn lot of work and I wouldn't want to do it.
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Sep 18th, 2001, 09:36 AM
#22
New Member
Chris
Have you been able to send a string or structure back to vb using a callback. I've have a simialar problem. I also need to retrieve a string (actually a structure) if i use the function MyOleString it works fine but I get an access violation error if I call it from within my vb callback.
Any ideas
Sonia
-
Sep 18th, 2001, 02:04 PM
#23
soniab: make sure ByVal and ByRef are used correctly:
Code:
public sub callback(val as long)
' use val -> access violation
end sub
// in the C-code
callback(2);
Ths is because standard parameter passing convention of VB is ByRef, so val is actuallly a pointer, but C passes the value. Then VB tries to dereference the pointer 0x00000002, causing an access violation. Always use ByVal for such things!
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Sep 18th, 2001, 03:07 PM
#24
New Member
Passing BSTR back to vb callback
Hi CorrnedBee
I am passing the string back to the vb callback Byval.
Something like this
Public function MyCallBack(Byval lNo as long,Byval lBuffer as long)
On the CPP side I pass the a long and bSTR (i've tried *BSTR) as well to the call back.
The lNo comes through fine.
The lBuffer contains a value. If I take the hex value of lBuffer it is the same memory address as the BSTR that I pass. I can even look at the memory in CPP and the string is there.
My Problem is I cant do anything with it Ive tried CopyMemory strlen - it all fails.
So What I tried is before i call the vb callback function i copy the data to a global cpp variable.
From the vb program I call a function that takes this global variable and pass it as a BSTR to vb. (This is the same function as Chris's OleString. It Works perfectly as long as I make this call outside my callback function.
If I put it inside I get the access violation.
Any Ideas
-
Sep 18th, 2001, 04:04 PM
#25
I'm not sure I understand. So what you do is:
VB some function -> calls some dll function -> copies a string into a global variable and calls vb callback -> calls a dll function that returns the global variable
Did I get this right? It wouldn't make sense to me.
Anyway I'm not very good at strings with vb/C. parksie is your man for this. Search for his name, you'll probably get more info than you ever want.
Maybe you could declare a byte array in vb and pass it to the dll using VarPtr(array(1)) (parameter type is ByVal as Long). The dll function could use it as char* and fill it with the string. Just an idea.
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Sep 18th, 2001, 07:10 PM
#26
It almost seems as if everyone is trying to do almost the same thing at the same time. I am trying to create a sort of EnumFiles function, that takes at address of a function in VB, and loops through each file in a package format that I have created, and give back a filename and file size. It doesnt work, and I cannot get to BSTR (any help on this, i dont know what headers to include, etc. I get some odd kind of error in one of the ole header files).
soniab, According to your declare, you are saying that lBuffer is a long, not a string. So, yes, you would get a value back. Something you could do, is create your callback function to reveive a pointer to a Byte Array, and loop through the array, and convert each value into a character. I think I may end up doing that.
Z.
-
Sep 18th, 2001, 07:40 PM
#27
Thread Starter
PowerPoster
CornedBee, you're right if using the LoadLibrary, GetProcAddress and FreeLibrary. It will be alot of work need to do and I also not prefer this (Link Explicitly) method.
Another, question i have over here
For instance, I have a global variable in my DLL, let make it 'TotalTime':
PHP Code:
long TotalTime=0;
can my external program using or refer to this dll but using the following declaration in respective header file.
external project name is abc.cpp & abc.h, so I declare this under the abc.h as
PHP Code:
extern long TotalTime;
regards,
soniab, I do facing the same problem as you encounter now. if you check through my sample code (MyDLL.cpp) I did remark some of the code by converting a normal char into BSTR (wchar) format:
(ANSI) Hello = (HEX) 72 101 108 108 111 0
To...
(BSTR) Hello = (HEX) 72 00 101 00 108 00 108 00 111 00 0
But I encounter some funny problem when I applied this code, perhaps you can get somethings out from there. Anyway, I still looking into this 
Zaei, as for the OLE header file, I use the ole2.h from the window itself. Not sure are you using the same header file?
regards,
Chris
-
Sep 19th, 2001, 09:23 AM
#28
chris: yes i think you can
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Sep 27th, 2001, 11:32 AM
#29
Thread Starter
PowerPoster
How can I export a class and it public function from a DLL? (Win32 Dynamic Link Library)
regards,
-
Sep 27th, 2001, 11:58 AM
#30
I'll explain soon, but I'm in a hurry.
Just this: if you want to use the class with VB you would have to create a CPM object. I have no idea how to do this.
Using it with C++ is pretty simple. More on that later or from parksie.
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Sep 27th, 2001, 12:08 PM
#31
Monday Morning Lunatic
Search the forum, I've posted on this before
I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You".
-- Linus Torvalds
-
Sep 27th, 2001, 01:03 PM
#32
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Sep 27th, 2001, 01:06 PM
#33
Monday Morning Lunatic
forums.vb-world.net is deprecated - use www.vbforums.com instead.
I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You".
-- Linus Torvalds
-
Sep 27th, 2001, 01:07 PM
#34
strange - I did the search and ended up with this URL
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Sep 27th, 2001, 04:03 PM
#35
Monday Morning Lunatic
All right, John? Got a new domain name? 
Weird
I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You".
-- Linus Torvalds
-
Sep 27th, 2001, 07:53 PM
#36
Thread Starter
PowerPoster
thx for the link.
BTW, i still have some doubt here... how your gy can explain more 
1. what the different when i export a class from a DLL, then import and use this class in an external app? as compare to the normal WIN32 DLL that I have created (posted sample code). Any advantages?
Since, my DLL also can create it own instance too.
2. Any advantages using the precompile directive as mention in the given link...
PHP Code:
#ifdef _IKDLL_INT
#define IKDLL __declspec(dllexport)
#else
#define IKDLL __declspec(dllimport)
#endif
class IKDLL MyClass {
// blah
};
regards,
-
Sep 27th, 2001, 08:12 PM
#37
Thread Starter
PowerPoster
CornedBee, i just go through your sample code (project.zip) and I have a short question here...
I got this from the classdll.h header file
PHP Code:
class MYAPI MyClass
{
public:
int getA();
int getB();
int getC();
void setA(int);
void setB(int);
void setC(int);
private:
int a, b, c;
};
if that the case, the external program will know the private funtion or varible use in the DLL itself. but actually, the external app shouldn't need to know right.
regards,
-
Sep 27th, 2001, 08:38 PM
#38
Fanatic Member
the app would only know about public methods like getA, getB, and getC
-
Sep 27th, 2001, 09:14 PM
#39
Thread Starter
PowerPoster
yup, Momad that my question, so why do we still need to declare those private variable and method in the external app?
-
Sep 27th, 2001, 09:58 PM
#40
Fanatic Member
you need the private variables to store your data.
your class should be like:
PHP Code:
class MYAPI MyClass
{
public:
int getA() { return _a; };
int getB() { return _b; };
int getC() { return _c; };
void setA(int a) { _a = a; };
void setB(int b) { _b = b; };
void setC(int c) { _c = x; };
private:
int _a, _b, _c;
};
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|