【问题标题】:SQLite UDF - VBA CallbackSQLite UDF - VBA 回调
【发布时间】:2010-09-09 01:52:27
【问题描述】:

是否有人尝试将 VBA(或 VB6)函数(通过 AddressOf ?)传递给 SQLite 创建 UDF 函数(http://www.sqlite.org/c3ref/create_function.html)。

VBA 将如何处理生成的回调参数?

要调用的函数将具有以下签名...

void (xFunc)(sqlite3_context,int,sqlite3_value**)

【问题讨论】:

    标签: vba sqlite vb6


    【解决方案1】:

    不幸的是,您不能直接使用 VB6/VBA 函数作为回调,因为 VB6 只生成 stdcall 函数,而不是 SQLite 期望的 cdecl 函数。

    您需要编写一个 C dll 来代理来回调用或重新编译 SQLite 以支持您自己的自定义扩展。

    重新编译你的dll将函数导出为stdcall后,你可以使用以下代码注册一个函数:

    'Create Function
    Public Declare Function sqlite3_create_function Lib "SQLiteVB.dll" (ByVal db As Long, ByVal zFunctionName As String, ByVal nArg As Long, ByVal eTextRep As Long, ByVal pApp As Long, ByVal xFunc As Long, ByVal xStep As Long, ByVal xFinal As Long) As Long
    
    'Gets a value
    Public Declare Function sqlite3_value_type Lib "SQLiteVB.dll" (ByVal arg As Long) As SQLiteDataTypes    'Gets the type
    Public Declare Function sqlite3_value_text_bstr Lib "SQLiteVB.dll" (ByVal arg As Long) As String        'Gets as String
    Public Declare Function sqlite3_value_int Lib "SQLiteVB.dll" (ByVal arg As Long) As Long                'Gets as Long
    
    'Sets the Function Result
    Public Declare Sub sqlite3_result_int Lib "SQLiteVB.dll" (ByVal context As Long, ByVal value As Long)
    Public Declare Sub sqlite3_result_error_code Lib "SQLiteVB.dll" (ByVal context As Long, ByVal value As Long)
    
    Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dest As Any, source As Any, ByVal bytes As Long)
    
    Public Property Get ArgValue(ByVal argv As Long, ByVal index As Long) As Long
        CopyMemory ArgValue, ByVal (argv + index * 4), 4
    End Property
    
    Public Sub FirstCharCallback(ByVal context As Long, ByVal argc As Long, ByVal argv As Long)
        Dim arg1 As String
        If argc >= 1 Then
            arg1 = sqlite3_value_text_bstr(ArgValue(argv, 0))
            sqlite3_result_int context, AscW(arg1)
        Else
            sqlite3_result_error_code context, 666
        End If
    End Sub
    
    Public Sub RegisterFirstChar(ByVal db As Long)
        sqlite3_create_function db, "FirstChar", 1, 0, 0, AddressOf FirstCharCallback, 0, 0
        'Example query: SELECT FirstChar(field) FROM Table
    End Sub
    

    【讨论】:

    • 我设法找到了一个 stdcall 友好的包装器,它还可以将 c 数组转换为安全数组等,因此调用非回调函数可以正常工作,它只是如何处理由 a 返回的类 c 结构回调,这是我的下一个问题。正如你所说,VBA 很可能会在达到这一点之前窒息。
    • 我已经设法修改 SQLite3VB 包装器以支持来自某些函数的 stdcall。由于我的更改非常复杂,因此我只发布了 VB 代码。如果您想要我对 SQLite 源代码所做的更改,请发布您的电子邮件以便我发送。也许在你可以在你的博客上发帖之后?
    • 太棒了,正是我想要的!如果您可以将 SQLite 源更改发送到“tom at gobansaor.com”,那就太好了。我正在整理各种 SQLite/ExcelVBA 代码位,然后将其发布在我的博客上,我一定会在我这样做时给你提一下。
    猜你喜欢
    • 2011-05-09
    • 1970-01-01
    • 2018-05-23
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-29
    相关资源
    最近更新 更多