2017-02-16 136 views
3

我已包裹sqlite3_opensqlite3_close,並從爲了SQLite的(3.16.2版)C-API sqlite3_exec例程將它們從使用ISO_C_BINDING模塊Fortran 2003的程序中調用。我使用Intel Fortran 17編譯器(ifort),在Windows上使用MSVC 14,在Linux上使用gcc。如何從sqlite3_open存儲數據庫連接句柄?

我的目標是打開的SQLite數據庫和存儲的指針數據庫連接手柄,這樣,當Fortran程序遍歷其計算,我可以用它來存儲/檢索結果。主程序的僞代碼看起來像這樣:

program main 
    use, intrinsic :: iso_c_binding 
    use sqlite_wrapper_module 
    implicit none 

    ! QUESTION: SHOULD DB_HANDLE BE TYPE(C_PTR) OR A STRUCT OF SOME KIND? 
    type(C_PTR) :: db_handle 

    character(len=:), allocatable :: db_name 

    db_name = "test.db"//C_NULL_CHAR 
    call sqlite3_open_WRAPPER(db_name, db_handle)  ! wraps sqlite3_open 

    do i=1,n 
    ...compute stuff... 
    call sqlite3_exec_WRAPPER(db_handle, sql_stmt) ! wraps sqlite3_exec 
    ...compute stuff... 
    enddo 

    call sqlite3_close_WRAPPER(db_handle)    ! wraps sqlite3_close 
end program main 

我已經在一個單獨的模塊中定義了封裝器C例程的顯式接口。例如:

module sqlite_wrapper_module 
    use, intrisic :: iso_c_binding 
    implicit none 
    interface 
    subroutine sqlite3_open_WRAPPER(db_name, db_handle) bind(C) 
     import 
     character(kind=C_CHAR), dimension(*) :: db_name 
     type(C_PTR), value :: db_handle 
    end subroutine sqlite3_open_wrapper 
    end interface 
end module sqlite_wrapper_module 

我不知道我理解的official docs,但他們似乎聲明* db是代表數據庫連接手柄,這是一個「不透明結構」定義爲typedef struct sqlite3 sqlite3;的指針。我不知道這到底意味着什麼(C編程不是我的強項)。所以我嘗試從Fortran設置C_PTR如下:

int sqlite3_open_WRAPPER(char *filename, sqlite3 *pdb) { 
    sqlite3 *db; 
    int rc=sqlite3_open(filename, &db); 
    pdb=db;  // <---------------------------------This 
    ...check rc... 
    return 0; 
} 

起初,這似乎工作。但是,鼠標指針返回NULL一次傳回Fortran程序,而不能在sqlite3_execsqlite3_close使用。我應該在Fortran程序中定義某種類型的struct作爲數據庫連接結構,並將其傳遞給C例程?

+1

使用標籤[tag:fortran]獲得更多關注。添加一個版本標籤來區分特定的版本,但這不適用於此,您的問題也適用於以後的版本。 –

回答

3

您分配一個值(db)一個局部變量(pdb),其生命時間函數結束,使用指針,以便使這些變化的函數外部可見的指針:

int sqlite3_open_WRAPPER(char *filename, sqlite3 *pdb) { 
    sqlite3 *db; 
    int rc=sqlite3_open(filename, &db); 
    pdb=db;  // <---------------------------------This 
    ...check rc... 
    return 0; 
} 

應該

int sqlite3_open_WRAPPER(char *filename, sqlite3 **pdb) { 
    sqlite3 *db; 
    int rc=sqlite3_open(filename, &db); 
    *pdb=db;  // <---------------------------------This 
    ...check rc... 
    return 0; 
} 

或更好,但直接使用pdb

int sqlite3_open_WRAPPER(char *filename, sqlite3 **pdb) { 
    int rc=sqlite3_open(filename, pdb); 
    ...check rc... 
    return 0; 
} 
+1

是的,這是問題和修復。正如你所建議的,我最終直接使用'pdb'。有趣的事情 - 我想過範圍/生活時間,我可以發誓我在發佈原始問題之前嘗試了這件事情......但是,一切都很好,結局很好! –