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()
,成功搞定,获取到了完整结果集。
相关阅读:
- nodejs调用dll/so文件的方法
- VS2013 生成sqlite3动态连接库及sqlite3.dll的调用
- ref
- ref *v0.3
- node-ffi
- sqlite3 example, how to got the col2 name and value?
- query multiple columns on the "sqlite.js" example
- ref-array
网友评论