SQLite UDF - VBA chamada de Retorno
Pergunta
Alguém já tentou passar uma VBA (ou VB6) função (via AddressOf ?) para o SQLite criar um UDF (função dehttp://www.sqlite.org/c3ref/create_function.html).
Como seria a resultante de retorno de chamada argumentos de ser manipulado pelo VBA?
A função a ser chamada, teria a seguinte assinatura...
void (xFunc)(sqlite3_context,int,sqlite3_value**)
Solução
Infelizmente, você não pode usar um VB6 e VBA assim uma função de retorno de chamada diretamente como VB6 só gera stdcall
funções, em vez de o cdecl
funções SQLite espera.
Você precisa escrever uma dll de C para o proxy as chamadas de e para trás ou recompilar o SQLite para suportar seu próprio extensão personalizada.
Depois de recompilar a dll para exportar as funções como stdcall
, você pode registrar uma função com o seguinte código:
'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