Ben al een tijdje bezig met een objectje te maken dat je vanuit excel moet kunnen aanroepen/gebruiken. Op zich werkt het geheel, echter heb ik een callback nodig.
Het probleem ligt hem erin dat de callback functie een cdecl functie is, welke natuurlijk niet zo gebruikt kan worden in VBA. Volgens MS Hier schrijven we MS moet je een wrapper functie bouwen om dit probleem te omzeilen.
Echter wat is het geval, ik heb een wrapper functie gebouwd welke dus mijn vba functie aanroept. Het aanroepen ansich gaat goed, maar nadat de vba functie klaar is krijg ik een c++ debug error. Klaarblijkelijk gaat er toch iets niet goed met de calling convention...
Debug error:
edit: (voor deze of gene met rare vragen omtrent pVal)
De code ansich lijkt gewoon goed gaan, want als ik dit doe in C#, dan gaat het gewoon goed.
Hier mijn vba code:
Het is idd niet de beste code die je kan schrijven, een int doorgeven als function pointer. Misschien dat daar ook wel de basis ligt van het probleem, het frapante is dat het wel goed werkt onder C#. Helaas ben ik gebonden aan een library die cdecl gebruikt en excel dat alleen stdcall aankan. Suggesties zijn natuurlijk altijd welkom
Ik heb al wel naar connection points gekeken, echter wil ik alleen een exception handler setten als er ook daadwerkelijk ééntje geset wordt vanuit vba. En ik ben nog niet in staat geweest om dit werkend te krijgen onder vba...vraag me uberhaupt af of dit wel mogelijk is.
Ik hoop dat iemand mij in de juiste richting kan sturen...ik zie namelijk niet goed wat er nou eigenlijk fout gaat... Ik heb een sterk vermoeden, maar ik snap dan niet goed wat er fout is aan mijn code.
Het probleem ligt hem erin dat de callback functie een cdecl functie is, welke natuurlijk niet zo gebruikt kan worden in VBA. Volgens MS Hier schrijven we MS moet je een wrapper functie bouwen om dit probleem te omzeilen.
Echter wat is het geval, ik heb een wrapper functie gebouwd welke dus mijn vba functie aanroept. Het aanroepen ansich gaat goed, maar nadat de vba functie klaar is krijg ik een c++ debug error. Klaarblijkelijk gaat er toch iets niet goed met de calling convention...
Debug error:
code:
1
| Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention. |
edit: (voor deze of gene met rare vragen omtrent pVal)
code:
1
| [id(79), helpstring("method SetExceptionHandler")] HRESULT SetExceptionHandler([in] INT pExceptionHandler, [out,retval] VARIANT_BOOL* pVal); |
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| typedef VOID (__cdecl *DBL_pFuncExceptionHandler)(INT dwErrorCode, VARIANT_BOOL blIsFatal); typedef LPVOID (__cdecl *tDBL_SetExceptionHandler)(DBL_pFuncExceptionHandler pExceptionHandler); typedef void (__stdcall CF_pFuncExceptionHandler)(INT dwErrorCode, VARIANT_BOOL blIsFatal); CF_pFuncExceptionHandler* Raise_ExceptionHandler; STDMETHODIMP CCFRONT::SetExceptionHandler(INT pExceptionHandler, VARIANT_BOOL* pVal) { if (CHECKFUNCPTR(DBL_SetExceptionHandler)) { if (DBL_SetExceptionHandler(&Callback_ExceptionHandler) != NULL) { Raise_ExceptionHandler = reinterpret_cast<CF_pFuncExceptionHandler*>(pExceptionHandler); *pVal = TRUE; } *pVal = FALSE; return S_OK; } return E_NOTIMPL; } VOID __cdecl Callback_ExceptionHandler(INT dwErrorCode, VARIANT_BOOL blIsFatal) { if (Raise_ExceptionHandler != NULL) { // Hieronder gaat het fout... Raise_ExceptionHandler(dwErrorCode, blIsFatal); } } |
De code ansich lijkt gewoon goed gaan, want als ik dit doe in C#, dan gaat het gewoon goed.
C#:
1
2
3
4
5
6
7
8
9
10
| delegate void DBL_pFuncExceptionHandler(int dwErrorCode, bool blIsFatal); public static void Test() { cf.SetExceptionHandler(Marshal.GetFunctionPointerForDelegate(new DBL_pFuncExceptionHandler(cf600_ExceptionHandler)).ToInt32()); } public static void cf600_ExceptionHandler(int dwErrorCode, bool blIsFatal) { } |
Hier mijn vba code:
Visual Basic:
1
2
3
4
5
6
7
| Private Function Test() cf.SetExceptionHandler(AddressOf CFRONT_ExceptionHandler) End Function Private Function CFRONT_ExceptionHandler(ByVal dwErrorCode As Long, ByVal blIsFatal As Boolean) MsgBox "blaat" End Function |
Het is idd niet de beste code die je kan schrijven, een int doorgeven als function pointer. Misschien dat daar ook wel de basis ligt van het probleem, het frapante is dat het wel goed werkt onder C#. Helaas ben ik gebonden aan een library die cdecl gebruikt en excel dat alleen stdcall aankan. Suggesties zijn natuurlijk altijd welkom
Ik heb al wel naar connection points gekeken, echter wil ik alleen een exception handler setten als er ook daadwerkelijk ééntje geset wordt vanuit vba. En ik ben nog niet in staat geweest om dit werkend te krijgen onder vba...vraag me uberhaupt af of dit wel mogelijk is.
Ik hoop dat iemand mij in de juiste richting kan sturen...ik zie namelijk niet goed wat er nou eigenlijk fout gaat... Ik heb een sterk vermoeden, maar ik snap dan niet goed wat er fout is aan mijn code.
[ Voor 3% gewijzigd door RobIII op 15-06-2009 18:33 . Reden: M$ :| ]