美文网首页
Node中通过使用FFI调用外部库文件

Node中通过使用FFI调用外部库文件

作者: 环零弦 | 来源:发表于2017-08-01 20:48 被阅读0次

    Node中通过使用FFI调用外部库文件

    因为NPM上的Sqlite3版本过于低了(3.1.8),有很多新的特性和性能提升没有及时更新,所以决定使用最新版本发布的dll/so文件作为方案。
    代码如下:

    var fs = require('fs')
      , ref = require('ref')
      , ffi = require('ffi')
      , ArrayType = require('ref-array')
    var dbName = process.argv[2] || 'test.sqlite3'
    var sqlite3 = 'void'
      , sqlite3Ptr = ref.refType(sqlite3)
      , sqlite3PtrPtr = ref.refType(sqlite3Ptr)
      , sqlite3_exec_callback = 'pointer'
      , stringPtr = ref.refType('string')
      , string = ref.types.CString
      , stringArray = ArrayType(string)
    
    var SQLite3 = ffi.Library('./wxsqlite3-sqlite3-aes128_x64/aes128/dll/release/sqlite3_x64', {
      'sqlite3_libversion': [ 'string', [ ] ],
      'sqlite3_open': [ 'int', [ 'string', sqlite3PtrPtr ] ],
      'sqlite3_close': [ 'int', [ sqlite3Ptr ] ],
      'sqlite3_changes': [ 'int', [ sqlite3Ptr ]],
      'sqlite3_exec': [ 'int', [ sqlite3Ptr, 'string', sqlite3_exec_callback, 'void *', stringPtr ] ],
      'sqlite3_key': ['int', [sqlite3Ptr, 'string', 'int']],
      'sqlite3_rekey': ['int', [sqlite3Ptr, 'string', 'int']]
    })
    
    var db = ref.alloc(sqlite3PtrPtr)
    SQLite3.sqlite3_open(dbName, db)
    db = db.deref()
    var x = process.argv[3];
    if(x === 'create'){
        // SQLite3.sqlite3_exec(db, 'CREATE TABLE tb_test (name VARCHAR, password VARCHAR, gender int, email VARCHAR, address VARCHAR);', null, null, null)
        // SQLite3.sqlite3_exec(db, 'INSERT INTO tb_test VALUES(\'randy3\', \'123456\', 0, \'typhoeus@163.com\', \'Changchun Jilin\');', null, null, null)
        SQLite3.sqlite3_exec(db, 'UPDATE tb_test SET name = \'Lily\' WHERE name = \'randy2\';', null, null, null)
    
        // SQLite3.sqlite3_rekey(db, '456', 3)
    
    } else {
        
        // SQLite3.sqlite3_key(db, '456', 3);
        // SQLite3.sqlite3_rekey(db, null, 0);
        var rowCount = 0
    
        var callback = ffi.Callback('int', ['void *', 'int', stringPtr, stringPtr], function (tmp, cols, argv, colv) {
            var obj = {}
            var colName = stringArray.untilZeros(colv).toJSON();
            var colData = stringArray.untilZeros(argv).toJSON();
            for (let i = 0; i < cols; i++) {
                obj[colName[i]] = colData[i]
            }
            console.log(obj);
            // console.log('Row: %j', obj)
            rowCount++
            return 0
        })
    
        var b = new Buffer('test')
        SQLite3.sqlite3_exec.async(db, 'SELECT * FROM tb_test;', callback, b, null, function (err, ret) {
            if (err) throw err
            console.log('Total Rows: %j', rowCount)
            //console.log('Changes: %j', SQLite3.sqlite3_changes(db))
            //console.log('Closing...')
            //SQLite3.sqlite3_close(db)
            //fs.unlinkSync(dbName)
            fin = true
        })
    }
    //SQLite3.sqlite3_close(db)
    
    
    /*
    module.exports = {
      fooSync : mylibrary.foo,
      foo: mylibrary.foo.async,
      barSync : mylibrary.bar,
      bar: mylibrary.bar.async
    };
    */
    

    ref这个很坑,完全看不懂好吧,不过官方有例子,正好又是跟我一样连的Sqlite3,省去无数麻烦,但有个缺点,只能获取第一列的数据,好在又有ref-array,不过也很难理解,最终凭经验猜到方法用toJSON(),成功搞定,获取到了完整结果集。


    相关阅读:


    拓展阅读:

    相关文章

      网友评论

          本文标题:Node中通过使用FFI调用外部库文件

          本文链接:https://www.haomeiwen.com/subject/ztdslxtx.html