Welcome, Guest
Username: Password: Remember me
  • Page:
  • 1

TOPIC:

Question about converting a function pointer to a delegate 13 Sep 2022 12:26 #23777

  • Kai
  • Kai's Avatar
  • Topic Author


  • Posts: 37
  • Hello everybody!

    I need your help again.
    I'm having trouble converting a function pointer from VO to a delegate in XSharp.

    The function worm_export_tar of the WORMAPI.DLL of the german "Kassensicherungsverordnung" needs a functionpointer to export data from the securitymodul (TSE = technische Sicherheitseinrichtung).

    WORMAPI.DLL was created by Swissbit who developed the TSE system.
    WORMAPI.DLL is not under my control and I assume that the functions it contains will work correctly.

    The worm_export_tar function makes multiple calls to a callback function and passes a memory pointer containing the data to be written to the export file.

    In VO the following code works fine:

    METHOD ExportTar(cDateiname AS STRING) AS INT PASCAL CLASS WormAccess
    LOCAL hFile AS PTR
    LOCAL nRet AS INT

    nRet := -1

    IF !(SELF:hWormContext == NULL_PTR)
    hFile := FCreate(cDateiname, FC_NORMAL)
    IF !(hFile == F_ERROR)

    //The pointer to the callback function is passed here

    nRet := worm_export_tar(SELF:hWormContext, @CallbackExportWormTar(), hFile)

    FClose(hFile)
    ELSE
    nRet := -2
    ENDIF
    ENDIF

    RETURN nRet

    //This is the callback-funkction which writes the data to the export-file:

    STATIC FUNCTION CallbackExportWormTar(hDaten AS PTR, nLen AS DWORD, hFile AS PTR) AS INT
    LOCAL nRet AS INT
    IF FWrite3(hFile, hDaten, nLen) == nLen
    nRet := 0
    ELSE
    nRet := -1
    ENDIF
    RETURN nRet


    STATIC GLOBAL hProc_worm_export_tar AS TF_worm_export_tar PTR

    FUNCTION TF_worm_export_tar(hWormContext AS PTR, hCallbackFunktion AS PTR, hFile AS PTR) AS INT PASCAL
    RETURN 0

    FUNCTION worm_export_tar(hWormContext AS PTR, hCallbackFunktion AS PTR, hFile AS PTR) AS INT PASCAL
    RETURN PCALL(hProc_worm_export_tar, hWormContext, hCallbackFunktion, hFile)



    In XSharp, the following code crashes exactly and reproducibly the third time the callback function is called. No error box is displayed, the program is simply terminated. The only difference between VO and XSharp is that XSharp uses the delegate to invoke the callback function.


    DELEGATE CallbackExportWormTar_delegate(hDaten AS PTR, nLen AS DWORD, hFile AS PTR) AS INT

    METHOD ExportTar(cDateiname AS STRING) AS INT PASCAL
    LOCAL hFile AS PTR
    LOCAL nRet AS INT
    STATIC LOCAL oCallbackExportWormTarDelegate AS CallbackExportWormTar_Delegate

    nRet := -1

    IF !(SELF:hWormContext == NULL_PTR)
    hFile := FCreate(cDateiname, FC_NORMAL)
    IF !(hFile == F_ERROR)

    oCallbackExportWormTarDelegate := CallbackExportWormTar

    nRet := worm_export_tar(SELF:hWormContext, System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(oCallbackExportWormTarDelegate), hFile)

    FClose(hFile)

    ELSE
    nRet := -2
    ENDIF
    ENDIF

    RETURN nRet

    STATIC FUNCTION CallbackExportWormTar(hDaten AS PTR, nLen AS DWORD, hFile AS PTR) AS INT
    LOCAL nRet AS INT
    IF FWrite3(hFile, hDaten, nLen) == nLen
    nRet := 0
    ELSE
    nRet := -1
    ENDIF
    RETURN nRet


    STATIC GLOBAL hProc_worm_export_tar AS TF_worm_export_tar PTR

    FUNCTION TF_worm_export_tar(hWormContext AS PTR, hCallbackFunktion AS PTR, hFile AS PTR) AS INT PASCAL
    RETURN 0

    FUNCTION worm_export_tar(hWormContext AS PTR, hCallbackFunktion AS PTR, hFile AS PTR) AS INT PASCAL
    RETURN PCALL(hProc_worm_export_tar, hWormContext, hCallbackFunktion, hFile)


    In both cases (VO and XSharp) the hProc_worm_export_tar variable is initialized once when the TSE system is started:

    hLibWorm := LoadLibrary(String2Psz("wormapi.dll"))
    hProc_worm_export_tar := GetProcAddress(hLibWorm, String2Psz("worm_export_tar"))


    So the question is: What is wrong with the delegate or the callback-function in XSharp what works fine in VO? What's weird is that it works twice and crashes on the third call in XSharp.

    Regards
    Kai

    Please Log in or Create an account to join the conversation.

    Question about converting a function pointer to a delegate 13 Sep 2022 13:15 #23779

    • Chris
    • Chris's Avatar


  • Posts: 3667
  • Hi Kai,

    Try running the app in debug mode (Debug->Start integrated debugging). you should get some runtime error message when the crash occurs.
    I assume you have set your app to be x86 mode? Also try changing the PTR in the delegate to IntPtr, should not make a difference, but just in case.
    Finally, can you produce a sample?

    .
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Question about converting a function pointer to a delegate 13 Sep 2022 13:28 #23782

    • wriedmann
    • wriedmann's Avatar


  • Posts: 3199
  • Hi Kai,
    I have created a X# COM library for this API for someone else and have used the C# WormCApi.dll for the interface to this DLL,
    Maybe it could be an idea to do the same and not do all work again.
    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    Question about converting a function pointer to a delegate 13 Sep 2022 13:57 #23783

    • leon-ts
    • leon-ts's Avatar


  • Posts: 238
  • Hi Kai,
    Try removing the STATIC modifier:
    STATIC FUNCTION CallbackExportWormTar
    As far as I understand, in X# it is equivalent to INTERNAL. This may block its call even though it is essentially converted to a direct pointer.

    Best regards,
    Leonid

    Please Log in or Create an account to join the conversation.

    Question about converting a function pointer to a delegate 13 Sep 2022 16:36 #23788

    • Kai
    • Kai's Avatar
    • Topic Author


  • Posts: 37
  • Hi!

    Removing static modifier didn't work.
    Unfortunately, changing PTR to intPtr didn't work either.

    The debugger reports:

    System.Reflection.TargetInvocationException
    Ein Aufrufziel hat einen Ausnahmefehler verursacht.

    Callstack :
    CCTouchpad.Boolean CCTouchpad.Klick(System.Int32 x, System.Int32 y)() : C:\XSharp\Kasse\PPKasseShare\PPKasseShare\CCTouchpad.prg : 1169
    CCTouchpad.__Usual CCTouchpad.Dispatch(XSharp.__Usual[] Xs$Args)() : C:\XSharp\Kasse\PPKasseShare\PPKasseShare\CCTouchpad.prg : 699
    XAPP.__Usual XAPP.Start(XSharp.__Usual[] Xs$Args)() : C:\XSharp\Kasse\PPKasseGastro\Start.prg : 386
    static Int32 PPKasseGastro.Exe.Functions.Start()() : C:\XSharp\Kasse\PPKasseGastro\Start.prg : 13

    None of the lines in the callstack seem to have anything to do with the callback function or the export

    Chris, I can produce a sample but you can't run it without a TSE.

    Please Log in or Create an account to join the conversation.

    Question about converting a function pointer to a delegate 13 Sep 2022 16:43 #23789

    • Chris
    • Chris's Avatar


  • Posts: 3667
  • Hi Kai,

    Does your Start() function have a [STAThread] attribute? If not, please add it and see it it makes a difference.

    Also what is the code around line 1169 in CCTouchpad.prg ?
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Last edit: by Chris.

    Question about converting a function pointer to a delegate 13 Sep 2022 16:55 #23791

    • Kai
    • Kai's Avatar
    • Topic Author


  • Posts: 37
  • Hi Chris!

    To make sure that the error has nothing to do with my custom control buttons (CCTouchpad), I created a simple application with just one standard button from the toolbox which starts te export from the TSE. When I click the button, the debugger reports:

    System.Reflection.TargetInvocationException
    Ein Aufrufziel hat einen Ausnahmefehler verursacht.

    Callstack :
    DialogHauptfenster.__Usual DialogHauptfenster.Dispatch(XSharp.__Usual[] Xs$Args)() : C:\XSharp\Kasse\Applications\Test\Prg\DialogHauptfenster.prg : 12
    XApp.__Usual XApp.Start(XSharp.__Usual[] Xs$Args)() : C:\XSharp\Kasse\Applications\Test\Prg\Start.prg : 17
    static Int32 Test.Exe.Functions.Start()() : C:\XSharp\Kasse\Applications\Test\Prg\Start.prg : 6

    The start-function has a [STAThread]; attribute

    [STAThread];
    FUNCTION Start() AS INT
    LOCAL oXApp AS XApp
    TRY
    oXApp := XApp{}
    oXApp:Start()
    CATCH oException AS Exception
    ErrorDialog(oException)
    END TRY
    RETURN 0

    CLASS XApp INHERIT App
    METHOD Start()
    LOCAL oWin AS DialogHauptfenster

    oWin := DialogHauptfenster{SELF}
    oWin:Show()

    SELF:Quit()

    RETURN SELF


    END CLASS

    Please Log in or Create an account to join the conversation.

    Question about converting a function pointer to a delegate 13 Sep 2022 17:07 #23792

    • comitas2
    • comitas2's Avatar


  • Posts: 33
  • Hi Kai,
    I created the following in Vulcan and ported it to X# some time ago as a test and there were no errors. Maybe there is something that will help you.
    [DllImport("WormAPI.dll", CallingConvention:=CallingConvention.Cdecl)] FUNCTION worm_export_tar(context AS IntPtr, callback AS WormExportTarCallback, callbackData AS IntPtr) AS INT PASCAL
    
    METHOD exportTar(callback AS WormExportTarCallback) AS VOID
    LOCAL result AS INT
    
    result := worm_export_tar(_MEMVARVO():worm_context, callback, IntPtr.Zero)
    IF (result != 0)
        THROW System.Exception{"Fehler beim Export: " + AllTrim(STR(result))} //springt in die nächst darübergelegene Catch-Fehler-Anzeige + RETURN
    ENDIF
    
    RETURN
    
    EXPORT worm_context AS IntPTR      //TSE Variable in übergeordneterStartklasse definiert
    
    
    METHOD btnExportTAR( )                      //bei click auf Export-Button
    LOCAL saveFile AS SaveFileDialog
    LOCAL cfileOut AS STRING
    LOCAL MyExport AS WormExportTarCallback
    
    IF !btnZugriff()
        RETURN NIL
    ENDIF
    
    TRY
        saveFile := SaveFileDialog{}
        saveFile:FileName := "tse.tar"
        saveFile:Filter := "TAR archive (*.tar)|*.tar|All files (*.*)|*.*"
        IF (saveFile:ShowDialog() != DialogResult.OK)
            RETURN
        ENDIF
    
        cfileOut     := saveFile:FileName
        stream2      := System.IO.FileStream{cfileOut,System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write}
        exportSize:=exportSize0:= myWorm:Info():tarExportSize()
        exportedSize := 0
    
    	oDCProgressBar1:Range := Range{1, 100}    //exportProgress.Value := 0
    	oDCProgressBar1:UnitSize := 10	// Setting the Unitsize
    	oDCProgressBar1:Position := 1 	// Setting the thumb to the start of the progress bar
    	oDCProgressBar1:show()    //exportProgress.Visible := TRUE
    
        MyExport := WormExportTarCallback{SELF,@WormExportTarCallback()}  //bei größeren Datenmengen wird ggf. WormExportTarCallback()von der LIB mehrfach gerufen
        myWorm:exportTar(MyExport)
    
    //    stream2:Close()
                
    CATCH e AS Exception
        ErrorBox{ NIL, e:Message }:Show()
        oDCtxtResult:TextValue :=  e:Message
        RETURN            
    FINALLY
        MessageBox.Show("Es wurden "+Str(exportedSize)+" Bytes exportiert.", "Export-Ergebnis:" , MessageBoxButtons.OK, MessageBoxIcon.Information)
    	oDCProgressBar1:Hide()  //    exportProgress.Visible = FALSE
    END TRY
    
    RETURN NIL
    
    METHOD WormExportTarCallback(chunk AS IntPtr, chunkLength AS DWORD, callbackData AS IntPtr ) AS INT
    //hier sollten die Daten aus dem Callback landen...
    LOCAL bytes AS BYTE[]
    LOCAL Len AS INT
    
    Len := (INT)chunkLength                                  //int Len = (int)chunkLength;
    IF (exportSize < chunkLength)                            // IF (mTSEExportSize < chunkLength)
        Len := (INT)exportSize                               // Len = (INT)mTSEExportSize;
    ENDIF
    
    bytes := BYTE[] {Len}                                    // BYTE[] ARRAY = new BYTE[Len]; //chunkLength
    Marshal.Copy(chunk, bytes, 0, Len)                       // Marshal.Copy(chunk, ARRAY, 0, Len); //(INT)chunkLength
    stream2:Write(bytes, 0, Len)                             // mTSETarExport.Write(ARRAY, 0, Len); //System.Buffer.ByteLength(bytes)
    exportedSize += (UInt64)Len                              //chunkLength
    exportSize   -= (UInt64)Len                              //mTSEExportSize -= (UInt64)Len //chunkLength
    bytes := NULL_OBJECT
    
    IF (exportSize == 0)                                     // IF (mTSEExportSize == 0)
        stream2:Close()                                      // mTSETarExport.Close();
    ENDIF
    
    oDCProgressBar1:Position := (INT) (100 * exportedSize / exportSize0)  //exportProgress.Value = (int) (100 * exportedSize / exportSize);
    ApplicationExec( ExecWhileEvent )  //Zeit zum Balken zeichnen 	
    
    RETURN 0

    Please Log in or Create an account to join the conversation.

    Question about converting a function pointer to a delegate 13 Sep 2022 17:07 #23793

    • Chris
    • Chris's Avatar


  • Posts: 3667
  • Hi Kai,

    What's the code around line 12 of DialogHauptfenster.prg ?
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Question about converting a function pointer to a delegate 13 Sep 2022 17:33 #23795

    • Kai
    • Kai's Avatar
    • Topic Author


  • Posts: 37
  • Chris, line 12 invokes the method ExportTar() from the code in my first post.

    Here is the full code of DialogHauptfenster:

    CLASS DialogHauptfenster INHERIT DialogHauptfensterAbstrakt
    CONSTRUCTOR(oOwner)
    SUPER(oOwner)
    RETURN
    METHOD ButtonTest AS VOID PASCAL
    LOCAL oWormAccess AS WormAccess
    LOCAL oTB AS TextBox

    oWormAccess := WormAccess{"T"}

    IF oWormAccess:nWormError == WORM_ERROR_NOERROR
    oWormAccess:ExportTar( "c:\test\export.tar") //Cris: Line 12
    oWormAccess:Destroy()

    oTB := TextBox{, "test", "OK"}
    oTB:Show()
    ELSE
    oTB := TextBox{, "test", "fehler"}
    oTB:Show()
    ENDIF
    METHOD Dispatch(oEvent)
    IF oEvent:Message == WM_COMMAND
    IF oEvent:wParam == IDCANCEL
    SELF:Enddialog()
    ENDIF
    ENDIF
    RETURN SUPER:Dispatch(oEvent)

    END CLASS



    If I remove the Dispatch-Method from the code the debugger reports:

    System.Reflection.TargetInvocationException
    Ein Aufrufziel hat einen Ausnahmefehler verursacht.

    Callstack :
    XApp.__Usual XApp.Start(XSharp.__Usual[] Xs$Args)() : C:\XSharp\Kasse\Applications\Test\Prg\Start.prg : 17
    static Int32 Test.Exe.Functions.Start()() : C:\XSharp\Kasse\Applications\Test\Prg\Start.prg : 6

    Please Log in or Create an account to join the conversation.

    Last edit: by Kai.

    Question about converting a function pointer to a delegate 13 Sep 2022 17:35 #23796

    • Kai
    • Kai's Avatar
    • Topic Author


  • Posts: 37
  • Hi Comitas2!

    Thank you for the code. If I need to rewrite this export function it will be very helpful.

    Kai

    Please Log in or Create an account to join the conversation.

    Question about converting a function pointer to a delegate 13 Sep 2022 17:45 #23798

    • Chris
    • Chris's Avatar


  • Posts: 3667
  • Hi Kai,

    In case this has something to do with the VOSDK getting in the way, please try using the same thing from a a WinForms application, does it work this way. If not, to see if it has to do with X# or not, please write the same test in c#, does it work there? If it does, then we will need to translate the code 1:1 to X# and it should work..
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    • Page:
    • 1