how to call a vb6 standalone exe module function from c/c++ new thread-reg
Hello The Trick,
I am working on a win32 c/c++ standard dll which calls a vb6 callback module function whose address is passed as parameter in new thread through its exported function.I have source code of this dll.
The vb6 callback module function is in standard exe.I do not have source code of this vb6 standard exe in which the above win32 standard dll is loaded.
When the vb6 standard exe tries to call the exported function of c/c++ dll by passing the address of the callback function as parameter the application crashes.
So I wanted to know is there any way to avoid this crash by modifying the following c/c++ dll source code.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Create an object in main STA and marshal the reference to the new thread using CoMarshalInterThreadInterfaceInStream/CoGetInterfaceAndReleaseStream pair but you need to initialize/support STA in new thread. The most simplier way i think is use windows messages (SendMessage). You can see this approach here. The calls from different threads are routed to the STA thread. https://www.vbforums.com/showthread....=1#post5551526
Last edited by The trick; Feb 18th, 2022 at 01:47 PM.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Hello The Trick,
I understood that dll async exported callback function is main thread assuming it is called from vb6 std exe.
I have to use either of two methods shown:
1. Create an object in main STA and marshal the reference to the new thread using CoMarshalInterThreadInterfaceInStream/CoGetInterfaceAndReleaseStream pair but you need to initialize/support STA in new thread. Can you provide me a simple code to achieve this in the dll code.
2.use windows messages (SendMessage). The calls from different threads are routed to the STA thread.I will go thru the given link and try and let you know.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Originally Posted by smkperu
1. Create an object in main STA and marshal the reference to the new thread using CoMarshalInterThreadInterfaceInStream/CoGetInterfaceAndReleaseStream pair but you need to initialize/support STA in new thread.
Can you provide me a simple code to achieve this in the dll code.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Hello The Trick,
I have gone thru the QPCTimer , VbVst-main.Both use activex dll in single threaded mode just like our standard dll c/c++ code.
Both route the new thread to the main STA thread.
But private objects of vb6 std exe are created in main thread instead of new thread which can be checked using GetCurrentThreaID() API in the dll code.
Now the left over part of the problem is
2. How to make the private objects of vb6 std exe created in new thread of dll again by modifying the c/c++ dll code.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
But private objects of vb6 std exe are created in main thread instead of new thread which can be checked using GetCurrentThreaID() API in the dll code.
A vb6 std-exe is STA-based one so all the objects live only in a single thread.
How to make the private objects of vb6 std exe created in new thread of dll again by modifying the c/c++ dll code.
If you want to break the rules. See this module again. This allows to create private objects in new threads.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Originally Posted by The trick
A vb6 std-exe is STA-based one so all the objects live only in a single thread.
If you want to break the rules. See this module again. This allows to create private objects in new threads.
Hello The Trick,
I want to create the same private objects in my new c/c++ dll thread without having to modify vb6 std exe since in the beginning itself I mentioned this.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Originally Posted by Schmidt
If you don't know how to do that in C++: ...ask in a C++ forum!
If you do know how to do that in C++: ...what do you need VB6 for?
It's becoming ridiculous.
Olaf
I barely understand any of the wizardry in this thread but what little I do get tells me this is more of a COM thing than a C++ thing. VB6 programmers tend towards being COM experts if nothing else
My impression is that OP is just way over his head.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Hello The Trick,
The following is the vb6 PrivateObjectCreatorofVB6Stdexe activex dll Project in single threaded mode CPrivateObjectCreatorofVB6Stdexe class code with CreatePrivateObjectByNameInNewThread() member function for which the private object is passed as String from exe:
CPrivateObjectCreatorofVB6Stdexe.cls code
Code:
Option Explicit
Private Sub Class_Terminate()
modMultiThreading.Uninitialize
End Sub
Public Sub createPrivateObjectinthread(ByVal str As String)
modMultiThreading.Initialize() 'initializes VB6Stdexe project using GetModuleHandle(0) for getting exe instance
Set frmexe = modMultiThreading.CreatePrivateObjectByNameInNewThread(str, , lId) 'exists in modMultiThreading2.bas
frmexe.Show
End Sub
You can take any simple vb6 stdexe and pass any of its private object say "Form1" as follows:
frmMain.frm code
Code:
Option Explicit
Dim mcCreator As PrivateObjectCreatorofVB6Stdexe.CPrivateObjectCreatorofVB6Stdexe
Private Sub Command1_Click()
mcCreator.createPrivateObjectinthread("Form1")
End Sub
Private Sub Form_Load()
Set mcCreator = New CPrivateObjectCreatorofVB6Stdexe
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set mcCreator = Nothing
End Sub
Just we have to add PrivateObjectCreatorofVB6Stdexe.dll to the vb6 stdexe thru project, references ,build and run the vb6 std exe in compiled mode.
If we don't want to use CPrivateObjectCreatorofVB6Stdexe in activex dll and and want only Exported function like CreatePrivateObjectByNameInNewThread, we can do that by modifying the LINKER SWITCHES and adding some initialization code in DLLMain().This exported function can be called in any vb6 std exe after declaring it in using Declare statement.
So I request you for the same PrivateObjectCreatorofVB6Stdexe.dll code in c/c++ which can work with any vb6 std exe.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Hello The Trick,
In order to run a module callback function from vb6 std exe from my c/c++ dll using your multithreading module in vb6 activex dll I made three projects:
1. Threadclient vb6 std exe ( which calls exported function of c/c++ win32 std dll)
3 vbcallback activex dll in (single threaded mode)
Details:
I made a simple activex dll (single threaded mode) vbcallback.dll containing Class1 multiuse class as follows using your modMultiThreading2.bas:
Class1.cls code
Code:
Option Explicit
Private Sub Class_Initialize()
modMultiThreading.Initialize 0
End Sub
Private Sub Class_Terminate()
modMultiThreading.Uninitialize
End Sub
Public Function InitCurrentThreadAndCallFunction( _
ByVal pfnCallback As Long, _
ByVal pParam As Long, _
ByRef lReturnValue As Long) As Boolean
modMultiThreading.InitCurrentThreadAndCallFunction _
pfnCallback, _
pParam, _
lReturnValue
End Function
Public Function InitCurrentThreadAndCallFunctionIDEProc( _
ByVal pfnCallback As Long, _
ByVal lParametersSize As Long) As Long
modMultiThreading.InitCurrentThreadAndCallFunctionIDEProc pfnCallback, _
lParametersSize
End Function
I made a standard win32 dll in c/c++ myvcdll.dll which
1.Exports fnMyvcdll function accepting module function pointer from any simple vb6 std exe
2. imports the above vbcallback.dll using #import which generated the .tli and tlh files.
Then I included the .tlh file using #include and called in a new thread as follows:
myvcdll.cpp code
Code:
_Class1Ptr cobj;//smart pointer
int ( __stdcall *lpVBFunction ) (int,int);
long glpfnTest;
DWORD WINAPI justDoIt(LPVOID lpParameter)
{
long retVal;
char tmp[50];
HRESULT hr11;
cobj->InitCurrentThreadAndCallFunction(glpfnTest,0,&retVal);//crashes at this line
sprintf(tmp, "Return Val from CallBack was %d", retVal);
MessageBox(0,tmp,"VB Callback Result",0);
return 0;
}
// This is an example of an exported function.
MYVCDLL_API int fnMyvcdll(long lpfnTest)
{
HANDLE hThrd;
DWORD tid;
glpfnTest=lpfnTest;
if((hThrd = CreateThread(
0,
0,
(LPTHREAD_START_ROUTINE)justDoIt,0,
0,
&tid)) == NULL)
{
//error handling here
}
CloseHandle(hThrd);
return 0;
}
In vb6 standard exe ThreadClient I called fnMyvcdll exported function by passing module function add as follows:
frmMain.frm code:
Code:
Option Explicit
Private Declare Function fnMyvcdll Lib "myvcdll.dll" _
(ByVal addr As Long) As Integer
Private Sub Command1_Click()
fnMyvcdll AddressOf add
End Sub
Module1.bas code:
Code:
Public Function add(ByVal a As Integer, ByVal b As Integer) As Long
MsgBox "in add"
add = a + b
End Function
But when I click on form button1 in vb6 std exe ThreadClient it crashes at the line
cobj->InitCurrentThreadAndCallFunction(glpfnTest,0,&retVal); in myvcdll.dll
Can you explain me how to avoid the crash and make my c/c++ dll call the callback of vb6 std exe
in new thread using vb6 activex dll.
If I can get cobj from this valid IDisp I can run
cobj->InitCurrentThreadAndCallFunction(glpfnTest,0,&retVal); How to get cobj from this valid IDisp
Thanks
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
You can't use this module for AxDll. If you need to callback of a function you could just use an object in the main (exe) thread. Just pass this object reference to another thread using marshaling. The callback will be in the main thread anywhere.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Originally Posted by The trick
You can't use this module for AxDll. If you need to callback of a function you could just use an object in the main (exe) thread. Just pass this object reference to another thread using marshaling. The callback will be in the main thread anywhere.
Can you show me an example code of using this between a simple vb6 standard exe module callback and c/c++ dll calling this vb6 callback in new thread
Option Explicit
Private Declare Function CreateThreadAndCallback Lib "dll" ( _
ByVal pfn As Long, _
ByVal l1 As Long, _
ByVal l2 As Long) As Long
Private Sub Command1_Click()
CreateThreadAndCallback AddressOf Callback, 123, 123000
End Sub
Code:
Option Explicit
Public Function Callback( _
ByVal l1 As Long, _
ByVal l2 As Long) As Long
Callback = l1 + l2
MsgBox Callback
End Function
2. Is there any way to use CreateThread instead of SHCreateThread since I never used SHCreateThread() and I am more familiar with simple CreateThread.If it is really required then OK.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
1. Learn C/C++. Probably you have no declarations for this API.
2. There is no difference. Just this function allows the thread handle not to be closed and does some initialization in the new thread before returns.
1. When set the build in debug mode and build dll and run vb6 std exe after displaying the correct msgbox and
when we click on the ok button of this msgbox I get the following error message box and app crashes.
---------------------------
Microsoft Visual C++ Debug Library
---------------------------
Debug Error!
The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
(Press Retry to debug the application)
---------------------------
Abort Retry Ignore
---------------------------
2. When set the build in release mode and build dll and run vb6 std exe the app immediately app crashes.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Hello Trick,
The crash got solved using_stdcall .
The MsgBox is displayed in main STA thread.
If we use modmultithreading module directly in the vb6 standard exe and call callback of vb6 standard exe from new thread of c/c++ standard dll using initcurrentthreadandcallfunction in callback we are achieving real threading in the sense the MsgBox is displayed in new thread without blocking main STA.
Now without using modmultithreading module in vb6 standard exe CAN we run MsgBox callback in c/c++ dll new thread without blocking main STA as above using SHCreateThread so that we can use this for any standard vb6 exe callback.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
The MsgBox is displayed in main STA thread.
I've already written it in #18 post.
It's possible but it requires to change the module to attach to a compiled project. BUT you can't just call already compiled code which doesn't expect threading. The most probably result is the crash.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Originally Posted by The trick
I've already written it in #18 post.
It's possible but it requires to change the module to attach to a compiled project. BUT you can't just call already compiled code which doesn't expect threading. The most probably result is the crash.
Hello Trick,
Already as you know ,
From a loaded vb6 activex dll in single threaded mode (using modMultiThreading2.bas) we can create a new thread and execute module function of any vb6 standard exe as follows :
hModule = GetModuleHandle(0) //get module instance of vb6 standard exe in which the dll is loaded
If pVBHeader Then
VBDllGetClassObject hModule , 0& , pNewHeader, aiid, tGuid, 0&
End If
Now we can list all modules and select one of the modules say module1 and its functions(callbacks) thru the above pVBHeader(as in CreatePrivateClass),
and run them using Dispcallfunc in this new thread.(Same method is used for CreateObjectbynameinnewthread)
Similarly can we load a c/c++ dll instead of vb6 activex dll as above ,create a new thread using CreateThread or SHCreateThread and in the new thread of c/c++ dll call the module callback of any vb6 standard exe using a simple example c/c++ code like standard win32 c/c++ dll code.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Hello Trick,
Any vb6 standard exe works fine in compiled mode when I use vbcallback single threaded activex dll which has multiuse class Class1 as follows:
Code:
Class1.cls code of vbcallback activex dll
Public Function InitCurrentThreadAndCallFunction( _
ByVal pfnCallback As Long, _
ByVal pParam As Long, _
ByRef lReturnValue As Long) As Boolean
modMultiThreading.InitCurrentThreadAndCallFunction pfnCallback, _
pParam, _
lReturnValue
End Function
Private Sub Class_Initialize()
modMultiThreading.Initialize 0
End Sub
Private Sub Class_Terminate()
modMultiThreading.Uninitialize
End Sub
Thru references when we add vbcallback.dll to any vb6 standard exe say genericvb6stdproj and call InitCurrentThreadAndCallFunction as follows:
Code:
Public Function MyCallBackFunction() As Long 'ByVal myIntArg As Long, ByVal myIntArg2 As Long) As Long
vbcallbackobj.InitCurrentThreadAndCallFunction AddressOf abc, 0, 0
End Function
Public Function abc() As Long
MsgBox "in vbcallback"' is displayed in new thread
abc = 0
End Function
in frmMain.frm of generic standard exe we have
Code:
Private Declare Sub CallFunctionPointer Lib "cstddll.dll" _
(ByVal lpfnMyFunc As Long)
Private Sub Command1_Click()
CallFunctionPointer AddressOf MyCallBackFunction
End Sub
Private Sub Command2_Click()
vbcallbackobj.CreatePrivateObjectByNameInNewThread "Form2"
End Sub
Private Sub Form_Load()
'modMultiThreading.Initialize
Set vbcallbackobj = New Class1
End Sub
Private Sub Form_Unload(Cancel As Integer)
'modMultiThreading.Uninitialize
End Sub
CallFunctionPointer is exported from our cstddll win32 c/c++ standard dll.It takes module function pointer as parameter and executes it in
new thread using CreateThread API.
So our vb6 standard exe interacts with cstddll(win32 c/c++ dll) as well as vbcallback singlethreaded actx dll for calling initcurrentthreadand callfunction
using Class1 object.
So our generic vb6 std exe is not depending on modmultithreading2.bas.It uses vbcallback actx dll for achieving this.
So now if we can move the functionality of vbcallback actx dll into our cstddll c/++ dll we will be having a single c/c++ dll with which we can interact with for achieving real multithreading ie. the MsgBox is displayed in new thread which we can check by moving main form after displaying the MsgBox for which I request your help.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Hello Trick,
Since cstddll is a c/c++ standard dll exporting "CallFunctionPointer",instead of using multiuse class I converted the vbcallback standard actx dll(single threaded) to export
functions Initialize ,Uninitialize ,InitCurrentThreadAndCallFunction by using DLLMain and in generic vb6 std exe(genericstdvb6exe) imported them as follows:
Code:
Public Declare Function Initialize Lib "vbcallback.dll" _
(hinstance As Long) As Boolean
Public Declare Sub Uninitialize Lib "vbcallback.dll" _
()
Public Declare Function InitCurrentThreadAndCallFunction Lib "vbcallback.dll" _
(ByVal pfnCallback As Long, _
ByVal pParam As Long, _
ByRef lReturnValue As Long) As Boolean
and called them as follows:
module1.bas code
Code:
Public Function MyCallBackFunction() As Long 'ByVal myIntArg As Long, ByVal myIntArg2 As Long) As Long
InitCurrentThreadAndCallFunction AddressOf abc, 0, 0 'calling exported function
End Function
frmMain.frm code
Code:
Private Declare Sub CallFunctionPointer Lib "cstddll.dll" _
(ByVal lpfnMyFunc As Long)
Private Sub Command1_Click()
CallFunctionPointer AddressOf MyCallBackFunction
End Sub
Private Sub Form_Load()
Initialize 0 'exported function
End Sub
Private Sub Form_Unload(Cancel As Integer)
Uninitialize 'exported function
End Sub
So now myprojupdated folder consists of three projects:
1.genericstdvb6exe
2.cstddll c/c++ dll
3.vbcallback activex dll single threaded now exporting Initialize ,Uninitialize ,InitCurrentThreadAndCallFunction.
genericstdvb6exe works fine.
Now you help me how to convert the above Initialize ,Uninitialize ,InitCurrentThreadAndCallFunction vbcallback activex dll exported functions to c/c++ code.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
What is this VB6 application that it is worth you spending this much effort on it? You've been spending months on some accessing some functionality, and it isn't working. I'm inclined to say that you're spending too much time on this for it to be justified. Perhaps there is a reason, but it sure doesn't look like it. You really need to step back and think this over before you continue bashing your head against this wall. So, what is the VB6 application? Why can't you replicate the functionality rather than even make use of the VB6 application?
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Originally Posted by Shaggy Hiker
What is this VB6 application that it is worth you spending this much effort on it? You've been spending months on some accessing some functionality, and it isn't working. I'm inclined to say that you're spending too much time on this for it to be justified. Perhaps there is a reason, but it sure doesn't look like it. You really need to step back and think this over before you continue bashing your head against this wall. So, what is the VB6 application? Why can't you replicate the functionality rather than even make use of the VB6 application?
Dear Shaggy Hiker,
I was trying to write a c/c++ dll which can call vb6 module callback of vb6 standard exe.I was experiencing a crash for which I took help of Trick with your permission.Trick gave me solution for the same except for private objects of vb6 std exe.But when I explored Tricks multithreading example for standard exe it worked well even for private objects .
So I tried using a vb6 activex dll single threaded in two ways for the same vb6 std exe as follows:
1.using multiuse class and its member functions.
2.using exported functions of vb6 directly using DLLMain initialization.
Both worked fine.
Now my last problem was why I am not able to solve the problem in c/c++ dll when I was able to solve it using vb6 actx dll for the same vb6 std exe.
If I am able to implement the exported function of vb6 vbcallback activex dll in
c/c++ I can put it directly in my c/++ dll and avoid two dlls.
This will help me develop applications in c/c++ which require multithreading explicitly as I did using createthread api and using readymade threading applications like using Multimedia timers for which the callbacks are by default multithreaded.
Dear Trick,
Having helped me upto this level in vb6,c/c++ and COM I think if you can provide me c/c++ code for InitCurrentThreadAndCallFunction exported function of vbcallback single threaded activex dll
I will mark this thread as resolved and thank you both Shaggy and Trick for the same.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Originally Posted by smkperu
This will help me develop applications in c/c++ which require multithreading explicitly...
Not sure, how VB6 enters the picture here...
VB6-threading is COM(STA)-based - whereas in C/C++ you can use "free-threading" directly -
(without any VB6 interaction, or any help from "ported VB6-codesnippets").
IMO you're asking your questions in the wrong forum (wasting everyones time).
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Originally Posted by Schmidt
Not sure, how VB6 enters the picture here...
VB6-threading is COM(STA)-based - whereas in C/C++ you can use "free-threading" directly -
(without any VB6 interaction, or any help from "ported VB6-codesnippets").
IMO you're asking your questions in the wrong forum (wasting everyones time).
Olaf
Hello Olaf,
This will help me develop applications in c/c++ which require multithreading explicitly impiles that using CreateThread in the context of vb6 standard exe thru c/c++ dll which I did in my c/c++ code .
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
just curious, do you have an actual project that needs this? I can not imagine a scenario where I would ever need this.
It sounds like the primary use would be a vb6 developer who wants to run his code in multiple threads. Not sure why
a C++ developer would go through all of this complexity just to reuse some vb6 code.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
It sure seems like you are making this vastly harder than it needs to be. C/C++ can do plenty of threading. VB6 can also do threading, though it takes a bit of work to get there. Why would you want to combine the two? If you're working in C/C++, then work in C/C++. You can do everything in there that you can do in VB6, and avoid this whole headache of trying to meld two languages. The great advantage of VB6 is rapid development and a nice form designer. You've kind of thrown out the first of those advantages when you decided to go with C/C++, so that leaves only the nice form designer. Forms and threading don't often play very nicely together, so the form designer alone doesn't seem sufficient reason for you to meld the two languages, which means there just isn't a good reason to do this. You can do multi-threading in VB6, you can do multi-threading in C/C++, you can also create forms in both (though it seems that this is still easier in VB6 for some reason), so what's the point of melding the two when it causes such pain?
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Hello The Trick,
I called exported InitCurrentThreadAndCallFunction from vbcallback.dll directly from c/c++ dll cbdll using
SHCreateThread by using the example provided by you in #20 as follows:
I am passing the pData->pfn(vb6 std exe callback) to exported InitCurrentThreadAndCallFunction (in vbcallback actx singlr threaded dll) as parameter instead of calling it directly (using IDispatch invoke()).
But still it crashes at the follwing line in the above code. fInitCurrentThreadAndCallFunction((long)pData->pfn,0,&retVal);//crashes at this line
How to avoid the crash and make the MsgBox display the addition result properly using this InitCurrentThreadAndCallFunction call .
Project attached.
cbproj folder contains
1.cb (vb std exe project)
2.In cb folder we have cbdll folder which is c/c++ dll project
3.vbcallback (vb activex single threaded dll exporting InitCurrentThreadAndCallFunction function)
Thanks
Last edited by Shaggy Hiker; Mar 10th, 2022 at 09:35 AM.
Reason: Removed attachment that contained compiled code.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Hello Trick,
The problem got solved when I called exported Initialize() function of vbcallback1 single threaded actx dll before calling SHCreateThread() in CreateThreadAndCallback().
Only final task left is vbcallback1 vb6 actx single threaded dll which is exporting Initialize ,Unitialize and InitCurrentThreadandCallFunction has to be implemented in c/c++.