2008-09-15 37 views
4

SQLiteにUBA関数(http://www.sqlite.org/c3ref/create_function.html)を作成するために誰かがVBA(またはVB6)関数を(AddressOf経由で)渡そうとしましたか?SQLite UDF - VBAコールバック

結果のコールバック引数はどのようにVBAによって処理されますか?

呼び出される関数は、次のシグネチャを持っているでしょう...

のボイド(xFunc)(sqlite3_context、int型、sqlite3_value **)残念ながら

答えて

4

、あなたは/ VB6を使用することはできませんVB6は、cdecl関数ではなく、stdcall関数を生成するだけで、VBA関数はコールバック関数として直接SQLiteに期待されます。

あなたは自分のカスタムエクステンションをサポートするために、コールを前後にプロキシするためにC dllを書くか、SQLiteを再コンパイルする必要があります。

stdcallとしての機能をエクスポートするためにあなたのdllを再コンパイルした後、次のコードで関数を登録することができます:私はまたなどセーフ配列のC arrayaを変換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 
+0

コールバック以外の関数を呼び出すことはうまくいきます。コールバックによって返されたCのような構造体を処理する方法は、次の問題です。 VBAは、その時点に達する前に非常にうまく消えてしまうかもしれないと言っています。 – gobansaor

+0

特定の関数からstdcallをサポートするようにSQLite3VBラッパーを変更することができました。私の変更がかなり関わっているので、私はVBコードを投稿しただけです。私がSQLiteソースに加えた変更をご希望の場合は、私が送ることができるようにあなたの電子メールを投稿してください。おそらくあなたのブログに投稿することができますか? – rpetrich

+0

これは、私が探していたものとまったく同じ優れたものです! SQLiteのソースの変更を "tom at gobansaor.com"に送ることができれば嬉しいです。私はさまざまなSQLite/ExcelVBAのコードビットを集めてブログに掲載しています。私はあなたの言葉を必ず伝えます。 – gobansaor