Page 1 of 2 12 LastLast
Results 1 to 40 of 72

Thread: how to Fast Call cdecl api like sqlite3.dll?

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2020
    Posts
    579

    how to Fast Call cdecl api like sqlite3.dll?

    With m_cCDECL
    sqlite3_exec = .CallFunc("sqlite3_exec", sqlite3, VarPtr(bvData(0)), 0, 0, 0)
    End With

    I WANT TO DO LIKE THIS:
    address1=GetProADDRESS (dll,"sqlite3_exec")

    bind_dllto_address(address1,addressof Mysqlite3_exec)

    function Mysqlite3_exec(ByVal sqlite3 As Long, ByVal zSql As long)
    'ASMCODE:
    'CALL address1(sqlite3 ,zSql )
    'clear something?
    end function


    this code maybe to slowly!
    Code:
    Public Function sqlite3_exec(ByVal sqlite3 As Long, ByVal zSql As String) As Long
        'int sqlite3_exec(
        '  sqlite3*,                                  /* An open database */
        '  const char *sql,                           /* SQL to be evaluated */
        '  int (*callback)(void*,int,char**,char**),  /* Callback function */
        '  void *,                                    /* 1st argument to callback */
        '  char **errmsg                              /* Error msg written here */
        ');
           
        Dim bvData()    As Byte
        Dim lSize       As Long
        Dim lRet        As Long
        
        If LenB(zSql) Then
            lSize = Len(zSql) * 4
            ReDim bvData(lSize)
        
            lRet = WideCharToMultiByte(CP_UTF8, 0, StrPtr(zSql), Len(zSql), bvData(0), lSize + 1, vbNullString, 0)
        
            If lRet Then
                ReDim Preserve bvData(lRet - 1)
            End If
        End If
    
        If m_bLoaded Then
            With m_cCDECL
                sqlite3_exec = .CallFunc("sqlite3_exec", sqlite3, VarPtr(bvData(0)), 0, 0, 0)
            End With
        Else
            sqlite3_exec = SQLITE_ERROR
        End If
    End Function
    Last edited by xiaoyao; Dec 5th, 2020 at 08:00 AM.

  2. #2

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2020
    Posts
    579

    Re: hao to call Sqlite3.dll with cdecl?

    HOW TO WRITE ASM CODE "PutAsmToMyFunctionAdress",BY writeProcessmemory
    ALSO CAN USE CdeclCallA:
    BUT I WANT TO Make a Function ,and Put Some asmcode,then
    no need for next

    Code:
    address1=GetProADDRESS (dll,"sqlite3_exec")
    
    PutAsmToMyFunctionAdress(addressof Mysqlite3_exec  ,  address1  , argCount=2)
    
    function Mysqlite3_exec(ByVal sqlite3 As Long, ByVal zSql As long)
      msgbox "asm code here"
      
    end function
    
    sub PutAsmToMyFunctionAdress(VBFunctionAddress,DllAddress,ArgCount)
    'writeProcessmemory -1, VBFunctionAddress,ASM CODE
    end sub
    
    function Mysqlite3_exec(ByVal sqlite3 As Long, ByVal zSql As long)
    'ASMCODE:
    'CALL address1(sqlite3 ,zSql )
    'clear something?
    end function
    
    dim i as long
    for i=1 to 10000
    
        Mysqlite3_exec(**,**)
    next
    Code:
    Public Function CdeclCallA(sDll As String, sFunc As String, ByVal RetType As VbVarType, ParamArray P() As Variant)
    Dim i As Long, pFunc As Long, V(), HRes As Long
     
      V = P 'make a copy of the params, to prevent problems with VT_Byref-Members in the ParamArray
      For i = 0 To UBound(V)
        If VarType(P(i)) = vbString Then P(i) = StrConv(P(i), vbFromUnicode): V(i) = StrPtr(P(i))
        VType(i) = VarType(V(i))
        VPtr(i) = VarPtr(V(i))
      Next i
      
      HRes = DispCallFunc(0, GetFuncPtr(sDll, sFunc), CC_CDECL, RetType, i, VType(0), VPtr(0), CdeclCallA)
      
      For i = 0 To UBound(P) 'back-conversion of the ANSI-String-Results
        If VarType(P(i)) = vbString Then P(i) = StrConv(P(i), vbUnicode)
      Next i
      If HRes Then Err.Raise HRes
    End Function
    Last edited by xiaoyao; Nov 28th, 2020 at 07:26 AM.

  3. #3
    Frenzied Member
    Join Date
    Jun 2012
    Posts
    1,663

    Re: hao to call Sqlite3.dll with cdecl?

    The fastest approach for VB6 is to compile the sqlite 3 library with __stdcall instead of __cdecl.

  4. #4

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2020
    Posts
    579

    Re: hao to call Sqlite3.dll with cdecl?

    Coders Corner - VB6 CDECL
    http://sandsprite.com/blogs/index.php?uid=11&pid=410

    http://sandsprite.com/CodeStuff/vb_cdecl.zip
    IT'S change VB Function To Cdecl,but i want to Call Vb Function Like Call Cdecl

    i want to call VB_Stdcall_Sum(11,22),it will call cdecl: test.dll sum(11,22)
    result=33


    what Code is For Build_CDecl_InVbStdcallFunction?

    Code:
    Function VB_Stdcall_Sum(ByVal x As Long,byval y as long ) As Long
      msgbox "Put AsmCode"
    end Function
    
    Function MyVB_Stdcall_CallBack(ByVal x As Long) As Long
        MsgBox "In VB call back! x=" & x
        MyVB_Stdcall_CallBack = x + 1
    End Function
    
    Function VB_CallBack2(ByVal x As Long, ByVal y As Long) As Long
        MsgBox "In VB_CallBack2 x=" & x & " y=" & y
        VB_CallBack2 = x - y
    End Function
    
        Build_CDecl_CallBack_Wrapper AddressOf VB_CallBack2, 2
    
        lpfnCallback2 = GetProcAddress(h, "CallBack2")
        ret = CallCdecl(lpfnCallback2, VarPtr(cdeclCallBackStub(0)), 2, 1)
    
     MsgBox "Callback2 Worked, results 2-1 = " & ret

  5. #5

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2020
    Posts
    579

    Re: hao to call Sqlite3.dll with cdecl?

    i want a way for call cdecl like call vb function,no need call api,no need DispCallFunc ,no need CallWindowProcA

    DispCallFunc 0, FuncAddr, 1, ReturnType, ParamCount, ParamTypes(0), ParamPtrs(0), CallCDECL

    VB_Stdcall_Sum=call test.dll cdecl function:sum
    Code:
    testaddress=getprocess("sum")  ' cdecl function from test.dll
    Build_CDecl_InVbStdcallFunction (testaddress,addressof VB_Stdcall_Sum,args=2)
    
    dim a as long,b as long ,c as long 
    a=11
    b=22
    c=VB_Stdcall_Sum(a,b)
    msgbox c=33
    
    
    Function VB_Stdcall_Sum(ByVal x As Long,byval y as long ) As Long
      msgbox "Put AsmCode"
    end Function

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2020
    Posts
    579

    Re: hao to call Sqlite3.dll with cdecl?

    some dll is __cdecl,and we have no source code,so only find a way call quickly
    why wen call cdecl function,exe cash?
    Code:
    Public Sub MakeFunctionCdecl_C(DllFunAddr As Long, BackFunAddr As Long, Args As Long)
    '
      Dim Code() As Byte, JmpBackAddr As Long
      Dim OldProtect As Long
      Dim ByteLen As Long
      ByteLen = 5 + Args
      ReDim Code(ByteLen)
      Vblegend.VirtualProtect ByVal DllFunAddr, ByteLen, 64, OldProtect   
      
      JmpBackAddr = DllFunAddr - BackFunAddr - 5
      Code(0) = &HE9
      Vblegend.CopyMemory Code(1), JmpBackAddr, 4
      Dim i As Long
      For i = 1 To Args
        Code(5 + i) = &H59 'pop ecx'恢复堆栈
      Next
      Vblegend.WriteProcessMemory -1, ByVal BackFunAddr, Code(0), ByteLen, 0
    End Sub
    Last edited by xiaoyao; Nov 28th, 2020 at 12:23 PM.

  7. #7

  8. #8

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2020
    Posts
    579

    Re: hao to call Sqlite3.dll with cdecl?

    Quote Originally Posted by The trick View Post
    You can call __cdecl functions directly in the compiled state if you declare __cdecl functions in a tlb without any tricks.
    IF IT'S NOT CALL api from sqlit3.dll,how to do?
    i put sqlit3.dll in 001.res,load res in memory,and call from Memory ADDRESS.
    HOW TO CALL CDECL API (address ) by asm?

    Code:
      Declare Function LoadLibrary Lib "kernel32.dll" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
      Declare Function FreeLibrary Lib "kernel32.dll" (ByVal hLibModule As Long) As Long
      Declare Function GetProcAddress Lib "kernel32.dll" (ByVal hModule As Long, ByVal lpProcName As String) As Long
      Declare Function DispCallFunc Lib "oleaut32.dll" (ByVal pvInstance As Long, ByVal offsetinVft As Long, ByVal CALLCONV As Long, ByVal retTYP As Integer, ByVal paCNT As Long, ByVal paTypes As Long, ByVal paValues As Long, ByRef retVAR As Variant) As Long
    
    Private Sub CallCDeclAPI()
    
        Dim fPtr As Long, hMod As Long
        Dim vParamType As Integer, vRtn As Variant, vParams As Variant
        Const CC_CDECL As Long = 1
    
        hMod = LoadLibrary("MyDLL.dll")
        If hMod Then
            fPtr = GetProcAddress(hMod, "SetNotificationProc")
            If fPtr Then
                vParams = pvGetAddrOf(AddressOf NewNotification)
                vParamType = vbLong
                DispCallFunc 0, fPtr, CC_CDECL, vbEmpty, 1, VarPtr(vParamType), VarPtr(vParams), vRtn
            End If
            FreeLibrary hMod
        End If
    End Sub
    Sub NewNotification()
    '
    End Sub
    Private Function pvGetAddrOf(inAddr As Long) As Long
        pvGetAddrOf = inAddr
    End Function
    Code:
    实用代码:VBAnyCall类任意调用函数代码(包括__cdecl调用约定的函数及汇编代码)
    VB
    >
    API
    收藏
    回复
    [问题点数:200分,结帖人supergreenbean]
    
    supergreenbean
    等级 
    勋章
    Blank
    Blank
    结帖率 100%
    '------------------------------ 类模块 VBAnyCall.cls ------------------------------
    Option Explicit
    '本模块名称
    Private Const THIS_MODULE_NAME As String = "CVBAnyCall"
    
    Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
    Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
    Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDest As Any, lpSource As Any, ByVal cBytes As Long)
    
    Private mlParameters() As Long '参数列表
    Private mlCallAddress As Long '调用的函数地址
    Private mbCodeBuffer() As Byte '汇编代码字节
    Private mlLastCodePosition As Long '用以跟踪最后添加的字节
    Private mbCodeBytes() As Byte '用于存储代码字节
    Private mfStdCall As Boolean '是否为__stdcall调用约定 True=__stdcall False=__cdecl
    
    '**************************************************************************
    '*                                暴露的接口                              *
    '**************************************************************************
    
    '调用汇编字节字符串方法
    'sCodeStr :汇编字节字符串
    'FuncParams():参数数组
    Public Function CallCodeBytes(ByVal sCodeStr As String, ParamArray FuncParams()) As Long
       On Error Resume Next
       Dim i As Long
       ReDim mlParameters(0)
       ReDim mbCodeBuffer(0)
       mlCallAddress = 0
       
       mbCodeBytes = ByteCodeStrToBin(sCodeStr)
       
       i = UBound(mbCodeBytes)
       
       If Err.Number <> 0 Then
          Call RaiseErr("代码字节字符串转换错误")
          Exit Function
       End If
       
       mlCallAddress = VarPtr(mbCodeBytes(0))
       
       If mlCallAddress = 0 Then
          Call RaiseErr("代码入口点地址错误")
          Exit Function
       End If
       ReDim mlParameters(UBound(FuncParams) + 1)
       For i = 1 To UBound(mlParameters)
          mlParameters(i) = CLng(FuncParams(i - 1))
       Next i
       
       CallCodeBytes = CallWindowProc(PrepareCode, 0, 0, 0, 0)
    End Function
    
    
    '按地址调用代码
    'lFuncAddress:函数地址
    'FuncParams():参数数组
    Public Function CallByAddress(ByVal lFuncAddress As Long, ParamArray FuncParams()) As Long
       Dim i As Long
       ReDim mlParameters(0)
       ReDim mbCodeBuffer(0)
       mlCallAddress = 0
       mlCallAddress = lFuncAddress
       If mlCallAddress = 0 Then
          Call RaiseErr("代码入口点地址错误")
          Exit Function
       End If
       ReDim mlParameters(UBound(FuncParams) + 1)
       For i = 1 To UBound(mlParameters)
          mlParameters(i) = CLng(FuncParams(i - 1))
       Next i
       CallByAddress = CallWindowProc(PrepareCode, 0, 0, 0, 0)
    End Function
    
    '调用DLL函数
    'sDllName:Dll名称
    'sFuncName:函数的名称
    'FuncParams():参数数组
    Public Function CallApiByName(ByVal sDllName As String, ByVal sFuncName As String, ParamArray FuncParams()) As Long
       Dim hLib As Long, i As Long
       ReDim mlParameters(0)
       ReDim mbCodeBuffer(0)
       mlCallAddress = 0
       hLib = LoadLibrary(ByVal sDllName)
       If hLib = 0 Then
          Call RaiseErr("Dll文件未找到")
          Exit Function
       End If
       mlCallAddress = GetProcAddress(hLib, ByVal sFuncName)
       If mlCallAddress = 0 Then
          Call RaiseErr("代码入口点地址错误")
          FreeLibrary hLib
          Exit Function
       End If
       ReDim mlParameters(UBound(FuncParams) + 1)
       For i = 1 To UBound(mlParameters)
          mlParameters(i) = CLng(FuncParams(i - 1))
       Next i
       CallApiByName = CallWindowProc(PrepareCode, 0, 0, 0, 0)
       FreeLibrary hLib
    End Function
    
    '汇编字节字符串转换为代码字节数组
    'sByteCode:汇编字节字符串
    Public Function ByteCodeStrToBin(ByVal sByteCode As String) As Byte()
        Dim s() As String
        Dim b() As Byte
        Dim i As Long
        
        s = Split(Trim(sByteCode), " ")
        
        If UBound(s) >= 0 Then
            ReDim b(UBound(s))
        End If
        
        For i = 0 To UBound(s)
            b(i) = CByte("&h" & s(i))
        Next
        ByteCodeStrToBin = b
    End Function
    
    '是否为__stdcall调用约定 True=__stdcall False=__cdecl
    Public Property Let IsStandardCall(fVal As Boolean)
        mfStdCall = fVal
    End Property
    
    Public Property Get IsStandardCall() As Boolean
        IsStandardCall = mfStdCall
    End Property
    '**************************************************************************
    '*                                暴露的接口                              *
    '**************************************************************************
    
    
    '**************************************************************************
    '******************************** 私有函数 ********************************
    '**************************************************************************
    Private Function PrepareCode() As Long
        Dim i As Long, lCodeStartPosition As Long
        ReDim mbCodeBuffer(18 + 32 + 6 * UBound(mlParameters))
        lCodeStartPosition = GetAlignedlCodeStartPosition(VarPtr(mbCodeBuffer(0)))
        mlLastCodePosition = lCodeStartPosition - VarPtr(mbCodeBuffer(0))
        For i = 0 To mlLastCodePosition - 1
            mbCodeBuffer(i) = &HCC
        Next
        AddByteToCode &H58 'pop eax'将返回地址存入eax
        AddByteToCode &H59 'pop ecx' / 去掉
        AddByteToCode &H59 'pop ecx'|  事先
        AddByteToCode &H59 'pop ecx'|  被压入
        AddByteToCode &H59 'pop ecx' \ 的参数
        AddByteToCode &H50 'push eax'重新压入返回地址
        For i = UBound(mlParameters) To 1 Step -1
            AddByteToCode &H68 'push parameter(i)'压入我们的参数
            AddLongToCode mlParameters(i)
        Next
        AddCallToCode mlCallAddress
        
        'VB之所以不能用__cdecl调用约定的函数就是因为VB不会自己恢复堆栈。
        If Not mfStdCall Then '如果调用约定不是__stdcall,那就自己恢复堆栈
            For i = 1 To UBound(mlParameters)
                AddByteToCode &H59 'pop ecx'恢复堆栈
            Next
        End If
        AddByteToCode &HC3
        AddByteToCode &HCC
        PrepareCode = lCodeStartPosition
    End Function
    
    Private Sub AddCallToCode(lAddr As Long)
        AddByteToCode &HE8
        AddLongToCode lAddr - VarPtr(mbCodeBuffer(mlLastCodePosition)) - 4
    End Sub
    
    Private Sub AddLongToCode(lCode As Long)
        Dim i As Integer
        Dim b(3) As Byte
        CopyMemory b(0), lCode, 4
        For i = 0 To 3
            AddByteToCode b(i)
        Next
    End Sub
    
    Private Sub AddByteToCode(bCode As Byte)
        mbCodeBuffer(mlLastCodePosition) = bCode
        mlLastCodePosition = mlLastCodePosition + 1
    End Sub
    
    Private Function GetAlignedlCodeStartPosition(lAddr As Long) As Long
        GetAlignedlCodeStartPosition = lAddr + (15 - (lAddr - 1) Mod 16)
        If (15 - (lAddr - 1) Mod 16) = 0 Then GetAlignedlCodeStartPosition = GetAlignedlCodeStartPosition + 16
    End Function
    
    Private Sub RaiseErr(ByVal sErrMsg As String)
        Err.Raise vbObjectError + &H1321, "VBAnyCall", sErrMsg
    End Sub
    Private Sub Class_Initialize()
        mfStdCall = True
    End Sub
    '**************************************************************************
    '******************************** 私有函数 ********************************
    '**************************************************************************
    
    2004-04-12 00:14:17楼主
    
    supergreenbean
    等级 
    勋章
    Blank
    Blank
    使用例子:
    '------------------------------ 窗体模块 Form1.frm ------------------------------
    Option Explicit
    '本模块名称
    Private Const THIS_MODULE_NAME As String = "Form1"
    
    Private goAnyCall As New CVBAnyCall
    
    Private WithEvents cmd As CommandButton
    Private WithEvents lst As ListBox
    
    Private Sub Form_Initialize()
        '使用SEH,防止程序崩溃
        'Call InitExceptionHandler
    End Sub
    
    Private Sub Form_Load()
        '移动窗体
        Me.Height = 5130
        Me.Width = 4935
        
        '添加按钮
        Set cmd = Me.Controls.Add("VB.CommandButton", "Command1")
        With cmd
            .Default = True
            .Caption = "运行例子"
            .Move 1290, 3990, 2235, 405
            .Visible = True
        End With
        
        '添加列表
        Set lst = Me.Controls.Add("VB.ListBox", "List1")
        With lst
            .Move 120, 120, 4575, 3480
            .Visible = True
        End With
    End Sub
    
    Private Sub cmd_Click()
        On Error GoTo Error_Handler
        Dim sByteCode As String
        Dim bBinCode() As Byte
        Dim i As Long
        Dim sDll As String
        i = 123
        sDll = "J:\User-C\CallTest\Debug\CallTest.dll"
        
        '运行汇编语言字节字符串
        lst.AddItem "直接运行汇编语言字节字符串,调用约定为__stdcall"
        sByteCode = "8B 44 24 04 C2 04 00"
        goAnyCall.IsStandardCall = True
        lst.AddItem "返回值:" & goAnyCall.CallCodeBytes(sByteCode, 123)
        
        lst.AddItem "直接运行汇编语言字节字符串,调用约定为__cdecl"
        sByteCode = "8B 44 24 04 C3"
        goAnyCall.IsStandardCall = False
        lst.AddItem "返回值:" & goAnyCall.CallCodeBytes(sByteCode, 123)
        
        '按地址运行汇编语言字节
        lst.AddItem "按地址运行汇编语言字节,调用约定为__stdcall"
        sByteCode = "8B 44 24 04 C2 04 00"
        bBinCode = goAnyCall.ByteCodeStrToBin(sByteCode)
        goAnyCall.IsStandardCall = True
        lst.AddItem "返回值:" & goAnyCall.CallByAddress(VarPtr(bBinCode(0)), 123)
        
        lst.AddItem "按地址运行汇编语言字节,调用约定为__cdecl"
        sByteCode = "8B 44 24 04 C3"
        bBinCode = goAnyCall.ByteCodeStrToBin(sByteCode)
        goAnyCall.IsStandardCall = False
        lst.AddItem "返回值:" & goAnyCall.CallByAddress(VarPtr(bBinCode(0)), 123)
        
        '按地址运行VB函数
        lst.AddItem "按地址运行VB函数,调用约定为__stdcall"
        lst.AddItem "i=" & CStr(i)
        goAnyCall.IsStandardCall = True
        lst.AddItem "返回值:" & goAnyCall.CallByAddress(AddressOf CallTest, VarPtr(i))
            
        '调用Dll函数
        'C函数原型
        'int __stdcall CallTestS(int *a){
        '    int b;
        '    b=*a;
        '    *a+=111;
        '    return b;
        '}
        lst.AddItem "调用Dll函数,调用约定为__stdcall"
        goAnyCall.IsStandardCall = True
        lst.AddItem "返回值:" & goAnyCall.CallApiByName(sDll, "CallTestS", VarPtr(i))
        lst.AddItem "i=" & CStr(i)
        
        'C函数原型
        'int __cdecl CallTestC(int *a){
        '    int b;
        '    b=*a;
        '    *a+=111;
        '    return b;
        '}
        lst.AddItem "调用Dll函数,调用约定为__cdecl"
        goAnyCall.IsStandardCall = False
        lst.AddItem "返回值:" & goAnyCall.CallApiByName(sDll, "CallTestC", VarPtr(i))
        lst.AddItem "i=" & CStr(i)
        
        Exit Sub
    Error_Handler:
        '自定义错误处理
    
        '调用默认错误处理函数
        'Call DefaultErrorHandler(THIS_MODULE_NAME)
    End Sub

  9. #9

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2020
    Posts
    579

    Re: hao to call Sqlite3.dll with cdecl?

    how to call cdecl_add by function VB_ADD(11,22)?

    Code:
    function VB_ADD(BYVAL A AS LONG ,byval b as long )
        msgbox "writeprocessMemory asm change code here"
    end function
    CDECL DLL
    Code:
    int __cdecl cdecl_add(int a, int b)
    {
        return a + b;
    }
    
    int main()
    {
        int x, y;
        x = stdcall_add(0x123, 0x456);
        y = cdecl_add(0x123, 0x456);
        return 0;
    }
    ASMCODE:
    
    
    004010B7  |.  8945 FC       mov     dword ptr [ebp-0x4], eax
    004010BA  |.  68 56040000   push    0x456
    004010BF  |.  68 23010000   push    0x123
    004010C4  |.  E8 41FFFFFF   call    0040100A                  ; __cdecl
    004010C9  |.  83C4 08       add     esp, 0x8                  ; 由调用者维持堆栈平衡
    004010CC  |.  8945 F8       mov     dword ptr [ebp-0x8], eax

  10. #10
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,168

    Re: hao to call Sqlite3.dll with cdecl?

    Quote Originally Posted by xiaoyao View Post
    ...how to call cdecl_add by function VB_ADD(11,22)?
    There is usually no need, to fumble around with ASM-Code (making your whole App a ticking time-bomb).

    Especially not in cases, where the (__cdecl-)function you plan to call, has to perform:
    - a whole lot of stuff internally (as e.g. the sqlite3_exec(...) function does, with dozens of sub-calls and operations)

    You still do not seem to understand, that a function-calls total-timing (until it returns) has two parts:
    1.) the call overhead (usually in the range of 1-100 nano-seconds)
    2.) the time the function itself needs (to process its "implementation", aka the instructions in its function-body)

    And since the above second part is (at least for sqlite3_exec) more in the range of micro-seconds,
    it does not really matter for the total call-time, if you were successfully:
    - reducing the __cdecl Call-Overhead from e.g. 100nano-seconds to perhaps 10nano-seconds with ASM-thunking
    - when the sqlite3_exec method itself takes about 10 micro-seconds for its internal instructions in addition

    To write it up in numbers... the total call-time for sqlite3_exec:
    - would be about 10.1 micro-seconds (using the established cdecl-call-workarounds without any ASM-tricks)
    - and it might be about 10.01 micro-seconds, if you manage the ASM-trickery successfully

    Congratulations then (in case you manage the ASM-trickery).
    You will then have succeeded, to call the sqlite3_exec function:
    - only about 1% faster over all (compared to using the established, stable VB6-cdecl calling methods alternatively)
    - whilst introducing a whole lot of potentially unstable, barely maintainable thunking-code into your App

    Not a good bargain at all, if you ask me.

    Olaf
    Last edited by Schmidt; Nov 29th, 2020 at 10:44 AM.

  11. #11

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2020
    Posts
    579

    Re: hao to call Sqlite3.dll with cdecl?

    sqlite3_exec,This function is 主要问题还是在于读写大量单元格十万个。The main problem is still reading and writing a large number of cells.It took me five seconds to read and write one compo我在读写Excel表格的一个组件中五万行十五列,用了五秒钟。I spent five seconds reading and writing fifty thousand rows and fifteen columns in one component of an Excel spreadsheet.it'S stdcall,if it'是cdecl,It could take 30 seconds.

  12. #12

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2020
    Posts
    579

    Re: hao to call Sqlite3.dll with cdecl?

    only use jmp。I don't think this will bring any performance loss.
    JmpBackAddr = DllFunAddr - BackFunAddr - 5
    Code(0) = &HE9

    However, this format does not support CDMAHowever, this format does not support cdeclI
    also can make a vb com objet to call,maybe slowly

  13. #13

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2020
    Posts
    579

    Re: hao to call Sqlite3.dll with cdecl?

    DispCallFunc
    methond 2by com),which quickly

    Code:
    'FunctionPtr.cls  '函数指针类的定义
    VERSION 1.0 CLASS
    BEGIN
      MultiUse = -1  'True
      Persistable = 0  'NotPersistable
      DataBindingBehavior = 0  'vbNone
      DatasourceBehavior  = 0  'vbNone
      MTSTransactionMode  = 0  'NotAnMTSObject
    END
    Attribute VB_Name = "FunctionPtr"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = True
    Attribute VB_PredeclaredId = False
    Attribute VB_Exposed = False
    Option Explicit
    
    Private Const DISPATCH_METHOD = &H1
    Private Const LOCALE_SYSTEM_DEFAULT = &H800
    Private Const DISPID_VALUE = 0
    
    Private Enum CALLCONV
      CC_FASTCALL = 0
      CC_CDECL = 1
      CC_MSCPASCAL = CC_CDECL + 1
      CC_PASCAL = CC_MSCPASCAL
      CC_MACPASCAL = CC_PASCAL + 1
      CC_STDCALL = CC_MACPASCAL + 1
      CC_FPFASTCALL = CC_STDCALL + 1
      CC_SYSCALL = CC_FPFASTCALL + 1
      CC_MPWCDECL = CC_SYSCALL + 1
      CC_MPWPASCAL = CC_MPWCDECL + 1
      CC_MAX = CC_MPWPASCAL + 1
    End Enum
    
    Private Type PARamdATA
      szName As String
      vt As VariantTypeConstants
    End Type
    
    Private Type METHODDATA
      szName As String
      ppdata As Long '/* pointer to an array of PARAMDATAs */
      dispid As Long  '/* method ID */
      iMeth As Long  '/* method index */
      cc As CALLCONV  '/* calling convention */
      cArgs As Long  '/* count of arguments */
      wFlags As Integer  '/* same wFlags as on IDispatch::Invoke() */
      vtReturn As Integer
    End Type
    
    Private Type INTERFACEDATA
      pmethdata As Long  '/* pointer to an array of METHODDATAs */
      cMembers As Long
    End Type
    
    Private Declare Function CreateDispTypeInfo Lib "oleaut32" (ByRef pidata As INTERFACEDATA, ByVal lcid As Long, ByRef pptinfo As IUnknown) As Long
    Private Declare Function CreateStdDispatch Lib "oleaut32" (ByVal punkOuter As IUnknown, ByRef pvThis As Delegator, ByVal ptinfo As IUnknown, ByRef ppunkStdDisp As IUnknown) As Long
    
    Private Type VTable
      pThunk As Long
    End Type
    
    Private Type Delegator
      pVtbl As Long
      pFunc As Long
    End Type
    
    Private m_Thunk(5) As Long
    
    Private m_VTable As VTable
    Private m_Delegator As Delegator
    Private m_InterfaceData As INTERFACEDATA
    Private m_MethodData As METHODDATA
    Private m_ParamData() As PARAMDATA
    Private m_FunctionPtr As Object
    
    Public Function Create(ByVal pFunc As Long, ByVal RetType As VariantTypeConstants, ParamArray ParamTypes() As Variant) As Object
     
      If TypeName(m_FunctionPtr) <> "Nothing" Then
      Set Create = m_FunctionPtr
      Exit Function
      End If
     
      Dim i As Long
      Dim p As Long
      Dim cParam As Long
      cParam = UBound(ParamTypes) + 1
     
      ReDim m_ParamData(cParam)
     
      If cParam Then
      For i = 0 To cParam - 1
      m_ParamData(i).vt = ParamTypes(i)
      m_ParamData(i).szName = ""
      Next
      End If
      m_MethodData.szName = "Invoke"
      m_MethodData.ppdata = VARPtr(m_ParamData(0))
      m_MethodData.dispid = DISPID_VALUE
      m_MethodData.iMeth = 0
      m_MethodData.cc = CC_STDCALL
      m_MethodData.cArgs = cParam
      m_MethodData.wFlags = DISPATCH_METHOD
      m_MethodData.vtReturn = RetType
     
      m_InterfaceData.pmethdata = VarPtr(m_MethodData)
      m_InterfaceData.cMembers = 1
    
      Dim ti As IUnknown
      Dim Result As IUnknown
      Set Result = Nothing
      i = CreateDispTypeInfo(m_InterfaceData, LOCALE_SYSTEM_DEFAULT, ti)
      If i = 0 Then
      m_VTable.pThunk = VarPtr(m_Thunk(0))
     
      m_Delegator.pVtbl = VarPtr(m_VTable)
      m_Delegator.pFunc = pFunc
      p = VarPtr(m_InterfaceData)
      p = VarPtr(m_Delegator)
      i = CreateStdDispatch(Nothing, m_Delegator, ti, Result)
      If i = 0 Then
      Set m_FunctionPtr = Result
      Set Create = m_FunctionPtr
      End If
      End If
    End Function
    
    Private Sub Class_Initialize()
      'thunk的机器码,加nop是为了清晰
      m_Thunk(0) = &H4244C8B  'mov ecx, [esp+4]  获得this pointer
      m_Thunk(1) = &H9004418B  'mov eax, [ecx+4]  nop  获得m_pFunc
      m_Thunk(2) = &H90240C8B  'mov ecx, [esp]  nop  得到返回地址
      m_Thunk(3) = &H4244C89  'mov [esp+4], ecx  保存返回地址
      m_Thunk(4) = &H9004C483  'add esp, 4  nop  重新调整堆栈
      m_Thunk(5) = &H9090E0FF  'jmp eax  跳转到m_pFunc
    End Sub
    
    'Helper.cls  '其实不是Helper,只是原来的名字而已,包含供测试的函数
    Attribute VB_Name = "Helper"
    Option Explicit
    
    Sub Test1(ByRef this As Long)
      MsgBox "Test1", vbOKOnly, "hehe"
    End Sub
    
    Sub Test(ByVal s As String)
      MsgBox s, vbOKOnly, "hehe"
    End Sub
     
     
    '测试程序 
    Option Explicit
    
    Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
    Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
    
    Private Sub Form_Load()
      Dim p As FunctionPtr
      Set p = New FunctionPtr
     
      Dim d As Object
      Set d = p.Create(AddressOf Test, vbEmpty, vbString)
     
      d.Invoke ("hehe")
     
      Dim hModUser32
      Dim pMessageBoxW As Long
     
      hModUser32 = GetModuleHandle("User32")
      pMessageBoxW = GetProcAddress(hModUser32, "MessageBoxW")
      Dim mbw As New FunctionPtr
      Dim MessageBoxW As Object
      Set MessageBoxW = mbw.Create(pMessageBoxW, vbLong, vbLong, vbString, vbString, vbLong)
      'MessageBoxA 0, "hehe,form MessageBoxA", "", 0
      MessageBoxW.Invoke 0, "hehe,form MessageBoxW", "", 0
    End Sub

  14. #14

  15. #15
    Fanatic Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,012

    Re: hao to call Sqlite3.dll with cdecl?

    Check this https://www.vbforums.com/showthread....winsqlite3-dll
    for using Sqlite, in Windows 10.

  16. #16
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Posts
    2,626

    Re: hao to call Sqlite3.dll with cdecl?

    Quote Originally Posted by The trick View Post
    You could use http://www.vbforums.com/showthread.p...sembler-Add-in to make simple asm trampolins.
    I though about tweaking the trampolines but for cdecl it would be more complicated.

    After the function returns the thunk will have to adjust stack with add esp, X to clear the arguments before returning control to caller function.

    So on entry the stack is ret_addr, arg1, arg2, arg3, ..., argN which has to be shuffled into arg1, arg2, arg3, ..., argN, ret_addr so to be able to execute a simple call cdecl_function : add esp, args_size : ret

    So this needs a rep movsb organized for the args on the stack (preserving esi/edi/ecx in the meantime) which is a bit more code that cannot be fit in 8 bytes as the original trampolines.

    cheers,
    </wqw>

  17. #17
    Frenzied Member
    Join Date
    Feb 2015
    Posts
    1,697

    Re: hao to call Sqlite3.dll with cdecl?

    wqweto, you could just save the ret_addr elsewhere like into unused last arg.
    For example:
    Code:
    BITS 32
    
    NUM_OF_ARGS equ 4
    
    pop eax	; get retaddr
    pop ecx	; get pfn
    
    mov [esp + NUM_OF_ARGS * 4], eax
    
    call ecx
    
    add esp, NUM_OF_ARGS * 4
    
    ret
    The corresponding VB6 function has the following form:

    Code:
    Public Function CallCdecl4( _
                    ByVal pfn As Long, _
                    ByVal lArg1 As Long, _
                    ByVal lArg2 As Long, _
                    ByVal lArg3 As Long, _
                    ByVal lArg4 As Long, _
                    Optional ByVal lRetSpace As Long) As Long
    End Function
    I've made small test project where you can call different C-runtime functions:

    Code:
    Option Explicit
    
    Private Declare Function LoadLibrary Lib "kernel32" _
                             Alias "LoadLibraryW" ( _
                             ByVal lpLibFileName As Long) As Long
    Private Declare Function GetProcAddress Lib "kernel32" ( _
                             ByVal hModule As Long, _
                             ByVal lpProcName As String) As Long
    
    Sub Main()
        Dim hMSVCrt         As Long
        Dim pfn_snwprintf   As Long
        Dim pfn_ultow       As Long
        Dim pfn_wcsupr      As Long
        Dim pfn_wstrtime_s  As Long
        Dim sBuffer         As String
        
        hMSVCrt = LoadLibrary(StrPtr("msvcrt"))
        
        pfn_snwprintf = GetProcAddress(hMSVCrt, "_snwprintf")
        pfn_ultow = GetProcAddress(hMSVCrt, "_ultow")
        pfn_wcsupr = GetProcAddress(hMSVCrt, "_wcsupr")
        pfn_wstrtime_s = GetProcAddress(hMSVCrt, "_wstrtime_s")
        
        sBuffer = String$(255, vbNullChar)
        
        CallCdecl4 pfn_snwprintf, StrPtr(sBuffer), Len(sBuffer), StrPtr("Test %ld"), 1234
        
        Debug.Print sBuffer
        
        CallCdecl3 pfn_ultow, &H80212123, StrPtr(sBuffer), 10
        
        Debug.Print sBuffer
        
        CallCdecl2 pfn_wstrtime_s, StrPtr(sBuffer), Len(sBuffer)
        
        Debug.Print sBuffer
        
        sBuffer = "HeLlO WoRlD!!!"
        
        CallCdecl1 pfn_wcsupr, StrPtr(sBuffer)
        
        Debug.Print sBuffer
        
    End Sub
    You just need to install the Add-in.
    Attached Files Attached Files

  18. #18
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Posts
    2,626

    Re: hao to call Sqlite3.dll with cdecl?

    Quote Originally Posted by The trick View Post
    wqweto, you could just save the ret_addr elsewhere like into unused last arg.
    Aaaa, this is a nice one!

    Probably something like this would work

    Code:
     0: 58                   pop         eax  
     1: 89 84 24 XX XX XX XX mov         dword ptr [esp+Xh],eax  
     8: 58                   pop         eax  
     9: FF D0                call        eax  
    11: 90                   nop  
    12: 90                   nop  
    13: 90                   nop  
    14: 81 C4 XX XX XX XX    add         esp,Xh  
    20: C3                   ret  
    21: 90                   nop  
    22: 90                   nop  
    23: 90                   nop  
    
    &H24848958, X, &H90D0FF58, &HC4819090, X, &H909090C3
    Didn't test it though.

    cheers,
    </wqw>

  19. #19
    Fanatic Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,012

    Re: hao to call Sqlite3.dll with cdecl?

    I would like to see an example, where we prepare an execution buffer, adding machine code and a pointer to a vb function, say in a module, so when we call that execution buffer, the machine code call back the function (or sub) in the module.
    I can use this to prepare from my M2000 interpreter compiled parts which when run can use modules from the M2000 environment, to print in the M2000 console (which is a picture box on a form).

  20. #20
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Posts
    2,626

    Re: hao to call Sqlite3.dll with cdecl?

    > so when we call that execution buffer. . .

    How do you call an execution buffer in VB6 is the problem. There is no need for an execution buffer to callback a function, just call the address of the function if you have a solution to the problem at hand, namely if you have an address of a function (external stdcall DLL or in a bas module w/ AddressOf MyFunction for instance) how do you call this function, pass parameters and receive result proper?

    Trampolines can solve this problem with minimal overhead.

    In this thread we discuss tweaking such trampolines to call cdecl compiled functions in external C/C++ DLLs like sqlite3.dll

    cheers,
    </wqw>

  21. #21
    Fanatic Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,012

    Re: hao to call Sqlite3.dll with cdecl?

    I can't understand your answer wqweto. Ok I know the scope of this thread is for trampolines for loaded functions. My word was for functions that we prepare in memory, say with cdecl convention call, and for call back from that functions. I have no idea how to do that. Sometime ago Trick response to me, but I didn't understood also. I use to write assembly for 6502, and some time for 8086, but I have no clear idea about the prolog and epilog for the calling. Also what happen if we stop execution on the call back function when we call it form machine code on IDE?

  22. #22
    Frenzied Member
    Join Date
    Feb 2015
    Posts
    1,697

    Re: hao to call Sqlite3.dll with cdecl?

    This example uses DispCallFunc to call the dynamic code:
    Code:
    Option Explicit
    
    Private Const HEAP_CREATE_ENABLE_EXECUTE    As Long = &H40000
    Private Const HEAP_NO_SERIALIZE             As Long = &H1
    
    Private Declare Function HeapCreate Lib "kernel32" ( _
                             ByVal flOptions As Long, _
                             ByVal dwInitialSize As Long, _
                             ByVal dwMaximumSize As Long) As Long
    Private Declare Function HeapDestroy Lib "kernel32" ( _
                             ByVal hHeap As Long) As Long
    Private Declare Function HeapAlloc Lib "kernel32" ( _
                             ByVal hHeap As Long, _
                             ByVal dwFlags As Long, _
                             ByVal dwBytes As Long) As Long
    Private Declare Function HeapFree Lib "kernel32" ( _
                             ByVal hHeap As Long, _
                             ByVal dwFlags As Long, _
                             ByRef lpMem As Any) As Long
    Private Declare Function GetMem4 Lib "msvbvm60" ( _
                             ByRef pSrc As Any, _
                             ByRef pDst As Any) As Long
    Private Declare Function DispCallFunc Lib "oleaut32.dll" ( _
                             ByRef pvInstance As Any, _
                             ByVal oVft As Long, _
                             ByVal cc As Long, _
                             ByVal vtReturn As VbVarType, _
                             ByVal cActuals As Long, _
                             ByRef prgvt As Any, _
                             ByRef prgpvarg As Any, _
                             ByRef pvargResult As Variant) As Long
    
    Sub Main()
        Dim pCode   As Long
        Dim hHeap   As Long
        Dim vRet    As Variant
        
        hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE Or HEAP_NO_SERIALIZE, 0, 0)
        pCode = HeapAlloc(hHeap, 0, 8)
        
        ' // Put code 
        ' // mov eax, XXXXXXX
        ' // call eax
        ' // ret
        
        GetMem4 &HB8&, ByVal pCode
        GetMem4 &HC3D0FF00, ByVal pCode + 4
        
        ' // Add callback
        GetMem4 FAR_PROC(AddressOf Callback), ByVal pCode + 1
        
        ' // Call dynamic code (STDCALL)
        DispCallFunc ByVal 0&, pCode, 4, vbLong, 0, ByVal 0&, ByVal 0&, vRet
        
        Debug.Print vRet
        
        HeapFree hHeap, 0, ByVal pCode
        HeapDestroy hHeap
        
    End Sub
    
    Private Function FAR_PROC( _
                     ByVal pfn As Long) As Long
        FAR_PROC = pfn
    End Function
    
    Private Function Callback() As Long
        Callback = 1234567
    End Function
    Alternatively you could calculate the relative CALL instruction but it requires an additional calculation. PUSH addr/RET sequence can be used as well.

  23. #23
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Posts
    2,626

    Re: hao to call Sqlite3.dll with cdecl?

    Quote Originally Posted by georgekar View Post
    My word was for functions that we prepare in memory, say with cdecl convention call, and for call back from that functions. I have no idea how to do that.
    You can use Visual Studio to write various functions with cdecl and stdcall calling conventions and so on (varargs etc.), call these from main and disassemble the emitted callsite code (with Ctrl+Alt+D shortcut) directly in VS IDE.

    This is what I usually do, certainly don't write ASM thunks by hand but use the comfortable VS IDE like this:

    Code:
    __declspec(naked) void asm_test()
    {
        __asm {
            pop     eax
            mov     [esp + 4*0x123456], eax
            pop     eax
            call    eax
            nop
            nop
            nop
            add     esp, 4*0x123456
            ret
            nop
            nop
            nop
        }
    }
    
    void __cdecl main()
    {
        int *p = (int *)asm_test;
        printf("&H%08X, &H%08X, &H%08X, &H%08X, &H%08X, &H%08X\n", p[0], p[1], p[2], p[3], p[4], p[5]);
    . . .
    cheers,
    </wqw>

  24. #24
    Fanatic Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,012

    Re: hao to call Sqlite3.dll with cdecl?

    Very Good. Supposed I want to call with a parameter, or two (as long, say pointers to anything). Trick show the way to call a function from asm, but without passing something to it. Alternative I can use another buffer to put what I want and the call back just take it from that buffer.

  25. #25

  26. #26

  27. #27
    Fanatic Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,012

    Re: hao to call Sqlite3.dll with cdecl?

    1. For SQLITE3, the sqite3 exec functions get a call back. Can I pass a vb6 module's sub or function? I have to prepare it with FAR_PROC function ?

    https://stackoverflow.com/questions/...ation/31168999

    2. I think that winsqlite3.dll, has no use of password (like we did in an MDB database). Is there any other sqlite3 dll which we can use and with enabled the password option? (I know the mr Olaf has in RCX (5, 6) the solution, but as you know I prefer something which I can study and perhaps change to suit my taste).

  28. #28
    Frenzied Member
    Join Date
    Feb 2015
    Posts
    1,697

    Re: hao to call Sqlite3.dll with cdecl?

    Quote Originally Posted by georgekar View Post
    1. For SQLITE3, the sqite3 exec functions get a call back. Can I pass a vb6 module's sub or function? I have to prepare it with FAR_PROC function ?

    https://stackoverflow.com/questions/...ation/31168999
    You should prepare trampolin to the stack conversion like that:
    Code:
    Option Explicit
    
    Private Const HEAP_CREATE_ENABLE_EXECUTE    As Long = &H40000
    Private Const HEAP_NO_SERIALIZE             As Long = &H1
    
    Private Declare Function HeapCreate Lib "kernel32" ( _
                             ByVal flOptions As Long, _
                             ByVal dwInitialSize As Long, _
                             ByVal dwMaximumSize As Long) As Long
    Private Declare Function HeapDestroy Lib "kernel32" ( _
                             ByVal hHeap As Long) As Long
    Private Declare Function HeapAlloc Lib "kernel32" ( _
                             ByVal hHeap As Long, _
                             ByVal dwFlags As Long, _
                             ByVal dwBytes As Long) As Long
    Private Declare Function HeapFree Lib "kernel32" ( _
                             ByVal hHeap As Long, _
                             ByVal dwFlags As Long, _
                             ByRef lpMem As Any) As Long
    Private Declare Function GetMem4 Lib "msvbvm60" ( _
                             ByRef pSrc As Any, _
                             ByRef pDst As Any) As Long
    Private Declare Function GetMem1 Lib "msvbvm60" ( _
                             ByRef pSrc As Any, _
                             ByRef pDst As Any) As Long
    Private Declare Function DispCallFunc Lib "oleaut32.dll" ( _
                             ByRef pvInstance As Any, _
                             ByVal oVft As Long, _
                             ByVal cc As Long, _
                             ByVal vtReturn As VbVarType, _
                             ByVal cActuals As Long, _
                             ByRef prgvt As Any, _
                             ByRef prgpvarg As Any, _
                             ByRef pvargResult As Variant) As Long
    
    Private m_hHeap As Long
    
    Sub Main()
        Dim pTrampoline As Long
        
        pTrampoline = PrepareCallbackTrampolinCDecl(AddressOf callback, 4)
        
        ' // Test
        MsgBox ApiCall(pTrampoline, vbLong, 1, 2, 3, 4)
            
        If pTrampoline Then HeapFree m_hHeap, 0, ByVal pTrampoline - 4
        If m_hHeap Then HeapDestroy m_hHeap
        
    End Sub
    
    Private Function PrepareCallbackTrampolinCDecl( _
                     ByVal pfnCallback As Long, _
                     ByVal bArgs As Byte) As Long   ' // Args should be less 32
        Dim pCode   As Long
        
        If m_hHeap = 0 Then
            
            m_hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE Or HEAP_NO_SERIALIZE, 0, 0)
            
            If m_hHeap = 0 Then
                Exit Function   ' // out of memory
            End If
            
        End If
        
        pCode = HeapAlloc(m_hHeap, 0, 24)
        
        GetMem4 &HA358&, ByVal pCode + 4
        GetMem4 &HE80000, ByVal pCode + 8
        GetMem4 &H83000000, ByVal pCode + 12
        GetMem4 &H25FF10EC, ByVal pCode + 16
        
        ' // Update references
        GetMem4 pCode, ByVal pCode + 6
        GetMem4 pfnCallback - (pCode + &HF), ByVal pCode + 11
        GetMem4 pCode, ByVal pCode + 20
        GetMem1 bArgs * 4, ByVal pCode + 17
        
        PrepareCallbackTrampolinCDecl = pCode + 4
        
    End Function
    
    Private Function callback( _
                     ByVal data As Long, _
                     ByVal argc As Long, _
                     ByVal ppargv As Long, _
                     ByVal ppazColName As Long) As Long
        
        ' // ...
        
        MsgBox data & " " & argc & " " & ppargv & " " & ppazColName
        
        callback = 12345
        
    End Function
    
    Private Function ApiCall( _
                     ByVal pfn As Long, _
                     ByVal retType As VbVarType, _
                     ParamArray params() As Variant) As Variant
        Dim types()     As Integer
        Dim list()      As Long
        Dim param()     As Variant
        Dim pIndex      As Long
        Dim ptrList     As Long
        Dim ptrTypes    As Long
        Dim resultCall  As Long
        Dim hLib        As Long
        Dim funcAddress As Long
     
        Const CC_CDECL    As Long = 1
    
        If LBound(params) <= UBound(params) Then
            
            ReDim list(LBound(params) To UBound(params))
            ReDim types(LBound(params) To UBound(params))
            ReDim param(LBound(params) To UBound(params))
            
            For pIndex = LBound(params) To UBound(params)
                param(pIndex) = params(pIndex)
                list(pIndex) = VarPtr(param(pIndex))
                types(pIndex) = VarType(param(pIndex))
            Next
            
            ptrList = VarPtr(list(LBound(list)))
            ptrTypes = VarPtr(types(LBound(types)))
            
        End If
     
        resultCall = DispCallFunc(ByVal 0&, _
                                  pfn, _
                                  CC_CDECL, _
                                  retType, _
                                  UBound(params) - LBound(params) + 1, _
                                  ByVal ptrTypes, _
                                  ByVal ptrList, _
                                  ApiCall)
                 
    
        If resultCall Then Err.Raise 5: Exit Function
        
    End Function

  29. #29
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    4,080

    Re: hao to call Sqlite3.dll with cdecl?

    Quote Originally Posted by georgekar View Post
    ..

    2. I think that winsqlite3.dll, has no use of password (like we did in an MDB database). Is there any other sqlite3 dll which we can use and with enabled the password option? (I know the mr Olaf has in RCX (5, 6) the solution, but as you know I prefer something which I can study and perhaps change to suit my taste).
    SQLite Encryption Extension
    https://www.sqlite.org/see/doc/trunk/www/readme.wiki

  30. #30
    Fanatic Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,012

    Re: hao to call Sqlite3.dll with cdecl?

    Thanks, Trick.
    @Arnoutdv, is any ready to use dll, or I have to compile one?

  31. #31
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Posts
    2,626

    Re: hao to call Sqlite3.dll with cdecl?

    Quote Originally Posted by The trick View Post
    Why do you use so many nops?
    NOPs do not take any CPU cycles on execution nowadays but I use these to align following offsets in the thunk so to make "codegen" of the variable NUM_OF_ARGS easier like this

    Code:
    Option Explicit
    
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    Private Declare Function VirtualProtect Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long
    
    Public Function Call_ultow(ByVal Pfn As Long, ByVal Value As Long, ByVal Str As Long, ByVal Radix As Long, Optional ByVal Spacer As Long) As Long
        pvPatchTrampoline AddressOf Module1.Call_ultow, 3
        Call_ultow = Call_ultow(Pfn, Value, Str, Radix)
    End Function
    
    Private Function pvPatchTrampoline(ByVal Pfn As Long, ByVal lNumParams As Long) As Boolean
        Const PAGE_EXECUTE_READWRITE As Long = &H40
        Const THUNK_SIZE    As Long = 21
        Dim bInIDE          As Boolean
        Dim aThunk(0 To 5)  As Long
     
        Debug.Assert pvSetTrue(bInIDE)
        If bInIDE Then
            Call CopyMemory(Pfn, ByVal Pfn + &H16, 4)
        Else
            Call VirtualProtect(Pfn, THUNK_SIZE, PAGE_EXECUTE_READWRITE, 0)
        End If
        '  0: 58                   pop         eax
        '  1: 89 84 24 XX XX XX XX mov         dword ptr [esp+Xh],eax
        '  8: 58                   pop         eax
        '  9: FF D0                call        eax
        ' 11: 90                   nop
        ' 12: 90                   nop
        ' 13: 90                   nop
        ' 14: 81 C4 XX XX XX XX    add         esp,Xh
        ' 20: C3                   ret
        aThunk(0) = &H24848958
        aThunk(1) = lNumParams * 4 + 4
        aThunk(2) = &H90D0FF58
        aThunk(3) = &HC4819090
        aThunk(4) = lNumParams * 4
        aThunk(5) = &HC3
        Call CopyMemory(ByVal Pfn, aThunk(0), THUNK_SIZE)
        '--- success
        pvPatchTrampoline = True
    End Function
    
    Private Function pvSetTrue(bValue As Boolean) As Boolean
        bValue = True
        pvSetTrue = True
    End Function
    This way Call_ultow is a self-modifying trampoline to a cdecl pfn that can be used like this

    Code:
    Option Explicit
    
    Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
    Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
    
    Private Sub Form_Click()
        Dim hLib            As Long
        Dim Pfn             As Long
        Dim sBuffer         As String
        
        hLib = LoadLibrary("msvcrt")
        Pfn = GetProcAddress(hLib, "_ultow")
        
        sBuffer = String(50, 0)
        Call_ultow Pfn, &H80212123, StrPtr(sBuffer), 10
        MsgBox "[" & Replace(sBuffer, vbNullChar, vbNullString) & "]"
    End Sub
    The extra Spacer parameter was the invention in this thread. Kudos!

    cheers,
    </wqw>

  32. #32

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2020
    Posts
    579

    Re: hao to call Sqlite3.dll with cdecl?

    I want call by vb function,without any api like resultCall = DispCallFunc

    Private Declare Function LoadLibrary Lib "kernel32"
    it'S also can bind to vb function or getprocaddress from load dll to memory.

    in first can make Wrapper or write vb function asm code.
    I will test which is Fastest。

    maybe DispCallFunc or "CallWindowProcA",someone is very slowly.
    which api call is best quickly?
    which asm is best?

    Although we can use a lot of ways to achieve, but the speed really varies a lot. We hope to find the best solution, but at the same time, each solution can be used as a reference for learning, so that we can improve the technology to a higher level.
    chinese:虽然我们可以用很多种方法去实现,但是速度真的相差很多。我们希望能够找到一种最佳的方案,但同时每一个方案都可以作为学习参考,这样我们才能够把技术提高到更高的境界。

  33. #33

  34. #34

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2020
    Posts
    579

    Re: hao to call Sqlite3.dll with cdecl?

    Public Function CallCdecl( _
    ByVal pfn As Long, _
    ByVal lArg1 As Long, _
    Optional ByVal lRetSpace As Long) As Long
    End Function
    Public Public Function CallCdecl2( _
    ByVal pfn As Long, _
    ByVal lArg1 As Long, _
    ByVal lArg2 As Long, _
    Optional ByVal lRetSpace As Long) As Long
    End Function
    Function CallCdecl3( _
    ByVal pfn As Long, _
    ByVal lArg1 As Long, _
    ByVal lArg2 As Long, _
    ByVal lArg3 As Long, _
    Optional ByVal lRetSpace As Long) As Long
    End Function

    Public Function CallCdecl4( _
    ByVal pfn As Long, _
    ByVal lArg1 As Long, _
    ByVal lArg2 As Long, _
    ByVal lArg3 As Long, _
    ByVal lArg4 As Long, _
    Optional ByVal lRetSpace As Long) As Long
    End Function


    how to remove lRetSpace,only like:
    Public Function CallCdecl( _
    ByVal pfn As Long, _
    ByVal lArg1 As Long) As Long

    CallCdecl=1 'chang code by asm
    End Function
    My idea is to construct five to ten general-purpose function can call all the APi after all.
    This is a one-size-fits-all approach, and I very much agree that t这是一种万能的方法,非常通用,当然最好的方法还是和原来的函数原型一模一样。It's a one-size-fits-all approach, very versatile. Of course, the best way is still the same as the original function prototype. Both of these methods are 这两种方法都是很好的,我们可以研究一下,每个人按照自己需要去使用。This is a universal method and very versatile. Of course, the best way is to be exactly the same as the original function prototype. Both of these methods are very good, we can study each person to use according to actual needs
    Last edited by xiaoyao; Nov 30th, 2020 at 12:45 PM.

  35. #35
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Posts
    2,626

    Re: hao to call Sqlite3.dll with cdecl?

    Quote Originally Posted by The trick View Post
    The other approach https://www.vbforums.com/showthread....g-functions-by the pointer but you have to change to support cdecl.
    I think I already had the same trampoline thunk tweaked for cdecl in my previous post or is it a different one?

  36. #36
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,168

    Re: hao to call Sqlite3.dll with cdecl?

    Quote Originally Posted by xiaoyao View Post
    I spent five seconds reading and writing fifty thousand rows and fifteen columns in one component of an Excel spreadsheet.
    Could you please post this test-project (with working code, as a *.zip, including the Excel-File) -
    so that one can see better, what the whole thing "is all about"?

    Olaf

  37. #37

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2020
    Posts
    579

    Re: hao to call Sqlite3.dll with cdecl?

    Quote Originally Posted by wqweto View Post
    I think I already had the same trampoline thunk tweaked for cdecl in my previous post or is it a different one?
    dose it support cdecl dll api?

  38. #38
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Posts
    2,626

    Re: hao to call Sqlite3.dll with cdecl?

    Quote Originally Posted by xiaoyao View Post
    dose it support cdecl dll api?
    In the snippet above Pfn is a cdecl function pointer to _ultow function in msvcrt DLL

    Code:
        hLib = LoadLibrary("msvcrt")
        Pfn = GetProcAddress(hLib, "_ultow")
    Implementing your CallCdecl, CallCdecl2, CallCdecl3 and CallCdecl4 is trivial using the Call_ultow function as a model but you cannot get rid of its Spacer parameter easy.

    The extra paramter is needed to simplify the thunk to 21 bytes only but feel free to enhance it with rep movsb and all the other necessary instructions to shuffle the parameters on the stack as discussed above. This would allow indeed not having an extra optional Spacer parameter on your CallCdeclXxx functions.

    cheers,
    </wqw>

  39. #39

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2020
    Posts
    579

    Re: hao to call Sqlite3.dll with cdecl?

    CAN YOU GIVE ME 6 SAMPLE?
    CallCdecl, CallCdecl2, CallCdecl3 and CallCdecl4 ,CallCdecl5,CallCdecl6

    put asm to address(funaddress, ParamArray params() As Variant) As Variant
    For pIndex = 0 To UBound(params)
    PUT ASM "rep movsb " & pIndex 4
    NEXT
    LIKE THIS?

  40. #40
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Posts
    2,626

    Re: hao to call Sqlite3.dll with cdecl?

    I already put more effort in this thread than I intended to, so I'll leave stack shuffling implementation to you.

    Now I'll go read some extra info about the great Visual Freebasic of China instead -- we already have enough links on topics about it here, don't we?

    cheers,
    </wqw>

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width