How to code and wrap with ctypes a python function needed as callback by sqlite3?

前端 未结 1 1849
失恋的感觉
失恋的感觉 2021-01-26 09:45

I\'m trying to perform sqlite3_exec from python to extract line by line the contents of a database. According to the C API, I need a Callback function which will pe

相关标签:
1条回答
  • 2021-01-26 10:07

    Tested in Python 2.7 and Python 3.6 (if you change the DLL path) using the following database:

    create table tbl1(one varchar(10), two smallint);
    insert into tbl1 values('hello',10);
    insert into tbl1 values('goodbye',20);
    

    Code:

    # I know, bad form, but it makes the code easier to read for an example
    from ctypes import *
    
    # This was missing the 2nd c_int parameter.
    CALLBACK = CFUNCTYPE(c_int, c_void_p, c_int, POINTER(c_char_p), POINTER(c_char_p))
    
    @CALLBACK
    def extractor(unused, num_columns, pcolumn, pcolumn_name):
        print(pcolumn[:num_columns])
        return 0 # needs to return 0 from callback or will abort.
    
    sqlite3DLL = CDLL(r"C:\Python27\DLLs\sqlite3.dll")
    SQLITE_OPEN_READONLY = 1 
    p_src_db = c_void_p()
    
    sqlite3DLL.sqlite3_open_v2(b'test.db', byref(p_src_db), SQLITE_OPEN_READONLY, None)
    # pass the handle returned by above as first parameter below
    sqlite3DLL.sqlite3_exec(p_src_db, b'SELECT * FROM tbl1', extractor, None, None)
    sqlite3DLL.sqlite3_close(p_src_db)
    

    Output:

    ['hello', '10']
    ['goodbye', '20']
    

    I also recommend setting argtypes because it helps catch type errors and for some parameter types (like c_double) it is required.

    sqlite3DLL.sqlite3_open_v2.argtypes = c_char_p, POINTER(c_void_p), c_int,c_char_p
    sqlite3DLL.sqlite3_open_v2.restype = c_int
    
    sqlite3DLL.sqlite3_exec.argtypes = c_void_p,c_char_p,CALLBACK,c_void_p,POINTER(c_char_p)
    sqlite3DLL.sqlite3_open_v2.restype = c_int
    
    0 讨论(0)
提交回复
热议问题