快速上手
安装和使用 Swordfish
安装编译
位于 lib/abi_0/ 或 lib/abi_1/ 目录下的 libSwordfish.so 使用 g++-8.4.0 编译,推荐也使用 g++-8.4.0 来编译项目。如果使用 clang 编译器,请确保添加编译参数 -stdlib=libstdc++。
在编译前请先安装如下依赖库:
zlib:执行sudo apt-get install zlib1g-dev
进行安装。-
执行以下指令进行编译:
export LD_LIBRARY_PATH=/path/to/swordfish/lib/dependency:$LD_LIBRARY_PATH mkdir build cd build cmake .. make -j8
编译完成后,会在 build/bin 目录下生成可执行文件。
运行可执行文件
在 build/bin 目录下运行可执行文件之前,请确保该目录中包含了 dolphindb.dos, dolphindb.lic 和 dolphindb.cfg 文件。用户根据需求配置 dolphindb.cfg 文件中的相关项。具体配置项请参考 DolphinDB 配置文档。
运行环境
在 main
函数代码体的开头,需要通过以下指令初始化 Swordfish 的运行环境:
DolphinDBLib::initializeRuntime();
在 main
函数代码体的结尾,需执行以下命令以销毁 Swordfish 运行环境:
DolphinDBLib::finalizeRuntime();
完整的代码结构如下:
# include "Swordfish.h"
int main() {
DolphinDBLib::initializeRuntime();
// 代码实现
DolphinDBLib::finalizeRuntime();
return 0;
}
数据类型和形式
Swordfish 支持数据类型和形式同 DolphinDB,请参考C++ 数据类型与形式。
对象创建
本节通过几个简单示例帮助用户了解如何在 Swordfish 中创建对象。参考 C++ 数据类型与形式了解更多对象创建和操作的方法。
创建标量
本节通过简单案例展示如何创建一个标量。
# include "Swordfish.h"
int main() {
DolphinDBLib::initializeRuntime();
// 创建一个 INT 标量
Int *b = new Int(12);
std::cout << b->getString() << std::endl;
// 创建一个 STRING 标量
String *str = new String("hello");
std::cout << str->getString() << std::endl;
// 创建一个 DOUBLE 标量
Double *d = new Double(10);
std::cout << d->getString() << std::endl;
// 创建一个 DECIMAL32 对象,指定小数位数和原始数据
Decimal<int> decimal1(2, 12345); // 小数位数为 2,原始数据为 12345
// 创建一个 DECIMAL64 对象,指定小数位数和原始数据
Decimal<long long> decimal2(5, 88); // 小数位数为 5,原始数据为 88
// 创建一个时间类型
Date *date1 = new Date(2024, 8, 14);
std::cout << date1->getString() << std::endl;
DolphinDBLib::finalizeRuntime();
return 0;
}
创建向量
本节通过简单案例展示如何创建一个向量。
# include "Swordfish.h"
int main() {
DolphinDBLib::initializeRuntime();
// 创建一个 DOUBLE 类型向量
VectorSP v1 = Util::createVector(DT_DOUBLE, 0, 100);
// 添加元素
std::vector<double> newData = {1.1, 2.2, 3.3};
v1->appendDouble(newData.data(), newData.size());
std::cout << v1->getDouble(1) << std::endl;
// 创建一个 STRING 类型向量
VectorSP v2 = Util::createVector(DT_STRING, 0);
// 添加元素
std::vector<string> newData2 = {"A", "B", "C"};
v2->appendString(newData2.data(), newData2.size());
std::cout << v2->getString() << std::endl;
DolphinDBLib::finalizeRuntime();
return 0;
}
创建元组
本节通过简单案例展示如何创建一个元组。
# include "Swordfish.h"
int main() {
DolphinDBLib::initializeRuntime();
// 创建一个元组
VectorSP tp = Util::createVector(DT_ANY, 0);
ConstantSP d1{new Double(1.1)};
ConstantSP d2{new String("A")};
//向元组追加 2 个元素
tp->append(d1);
tp->append(d2);
//检查是否为元组,返回 1
std::cout << tp->isTuple() << std::endl;
DolphinDBLib::finalizeRuntime();
return 0;
}
创建数据对
本节通过简单案例展示如何创建一个数据对。
# include "Swordfish.h"
int main() {
DolphinDBLib::initializeRuntime();
// 创建一个 DOUBLE 类型的数据对
VectorSP p = Util::createPair(DT_DOUBLE);
p->setInt(0, 1.1);
p->setDouble(1, 3.6);
//检查是否为数据对,返回 1
std::cout << p->isPair() << std::endl;
DolphinDBLib::finalizeRuntime();
return 0;
}
创建矩阵
本节通过简单案例展示如何创建一个矩阵。
# include "Swordfish.h"
int main() {
DolphinDBLib::initializeRuntime();
int *rawData = new int[12]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
VectorSP m1 = Util::createMatrix(DT_INT, 4, 3, 12, 0, rawData);
DolphinDBLib::finalizeRuntime();
return 0;
}
/* output:
#0 #1 #2 #3
-- -- -- --
1 4 7 10
2 5 8 11
3 6 9 12
*/
创建字典
本节通过简单案例展示如何创建一个字典。
# include "Swordfish.h"
int main() {
DolphinDBLib::initializeRuntime();
// 创建一个字典
DictionarySP d1 = Util::createDictionary(DT_INT, nullptr, DT_DOUBLE, nullptr);
// 添加新的键值对
ConstantSP k = Util::createConstant(DT_INT);
k->setInt(1);
ConstantSP v = Util::createConstant(DT_DOUBLE);
v->setDouble(1.1);
d1->set(k, v);
k->setInt(2);
v->setDouble(2.2);
d1->set(k, v);
std::cout << d1->getString() << std::endl;
DolphinDBLib::finalizeRuntime();
return 0;
}
创建集合
本节通过简单案例展示如何创建一个集合。
# include "Swordfish.h"
int main() {
DolphinDBLib::initializeRuntime();
// 创建一个集合
SetSP s1 = Util::createSet(DT_INT, nullptr, 3);
// 添加一个元素
ConstantSP val = Util::createConstant(DT_INT);
val->setInt(1);
s1->append(val);
val->setInt(2);
s1->append(val);
std::cout << s1->getString() << std::endl;
DolphinDBLib::finalizeRuntime();
return 0;
}
创建表
本节通过简单案例展示如何创建一个内存表。
# include "Swordfish.h"
int main() {
DolphinDBLib::initializeRuntime();
// 创建表
std::string colName1 = "id";
std::string colName2 = "val";
std::vector<std::string> colNames = {colName1, colName2};
std::vector<DATA_TYPE> colTypes = {DT_INT, DT_DOUBLE};
TableSP tb1 = Util::createTable(colNames, colTypes, 0, 0);
// 插入行
std::string errMsg;
ConstantSP id = Util::createConstant(DT_INT);
ConstantSP val = Util::createConstant(DT_DOUBLE);
for (auto i = 0; i < 10; ++i)
{
id->setInt(i);
val->setDouble(i * 1.1);
std::vector<ConstantSP> rowValues = {id, val};
INDEX rowIdx = i;
tb1->append(rowValues, rowIdx, errMsg);
}
if (errMsg.empty())
{
std::cout << tb1->getString() << std::endl;
}
else
{
std::cout << "insert rows failed! " << errMsg << std::endl;
}
DolphinDBLib::finalizeRuntime();
return 0;
}
对象操作
本节以向量和表为例,简单展示如何进行对象操作。
向量操作
基于上节创建的 DOUBLE 类型向量 v1,进行一些向量操作。
-
向量写入元素
// 追加 1 个元素 1.5 v1->append(new Double(1.5)); // v1: [1.1,2.2,3.3,1.5] // 连续追加 3 个元素 2 v1->append(new Double(2), 3); // v1: [1.1,2.2,3.3,1.5,2,2,2]
-
读取向量数据
ConstantSP e1 = v1->get(0); //e1 为 DT_DOUBLE 类型的标量,值是1.1 double e2 = v1->getDouble(1); //e2: 2.2
-
修改向量数据
v1->set(1, new Double(100)); // vi: [1.1,100,3.3,1.5,2,2,2]
-
删除向量数据
// 删除指定索引的元素 ConstantSP index = Util::createIndexVector(3, 1); v1->remove(index); vi: [1.1,100,3.3,2,2,2] // 删除最后 4 个元素 v1->remove(4); // [1.1,100]
表操作
基于上节创建的表 tb1,进行一些表操作。
-
读取列数据
// 读取第 1 列 VectorSP col1 = tb1->getColumn(0); // [0,1,2,3,4,5,6,7,8,9] // 读取 val 列 VectorSP col2 = tb1->getColumn("val"); //[0,1.1,2.2,3.3,4.400000000000001,5.5,6.600000000000001,7.700000000000001,8.8,9.9]
-
读取行数据
// 读取第 1 行数据 DictionarySP row = tb1->get(0); std::cout << row->getString() << std::endl; /* output: id->0 val->0 */
-
向表中添加数据
INDEX insertedRows; std::string errorMsg; VectorSP col0 = Util::createVector(DT_INT, 0); VectorSP col1 = Util::createVector(DT_DOUBLE, 0); col0->append(new Int(20)); col1->append(new Double(30.5)); vector<ConstantSP> values{col0, col1}; tb1->append(values, insertedRows, errorMsg); std::cout << tb1->getString() << std::endl; /* output: id val -- ----------------- 0 0 1 1.1 2 2.2 3 3.3 4 4.400000000000001 5 5.5 6 6.600000000000001 7 7.700000000000001 8 8.8 9 9.9 20 30.5 */
-
修改某行数据
VectorSP col1 = tb1->getColumn(0); VectorSP col2 = tb1->getColumn("val"); // 通过修改每列的第 3 个元素,来修改表的第 3 行数据 col1->set(2, new Int(100)); col2->set(2, new Double(32.597)); std::cout << tb1->getString() << std::endl; /* output: id val --- ------------------ 0 0 1 1.1 100 32.597000000000001 3 3.3 4 4.400000000000001 5 5.5 6 6.600000000000001 7 7.700000000000001 8 8.8 9 9.9 */
通用计算函数
Swordfish 定义了一系列通用计算函数,用于执行各种数据操作和计算,包括运算符、聚合函数、向量函数等。本节以 cumsum
和
mavgTopN
为例,简单介绍如何使用通用函数。
-
使用计算函数前,需要引入头文件 OperatorImp.h。为方便函数调用,建议同时引入其命名空间。
#include "OperatorImp.h" using namespace OperatorImp;
-
调用
cumsum
计算向量元素的累加和# include "Swordfish.h" #include "OperatorImp.h" using namespace OperatorImp; int main() { DolphinDBLib::initializeRuntime(); VectorSP v1 = Util::createVector(DT_INT,0); std::vector<int> newData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; v1->appendInt(newData.data(), newData.size()); ConstantSP result = OperatorImp::cumsum(v1,Expression::void_); std::cout <<result->getString() << std::endl; DolphinDBLib::finalizeRuntime(); return 0; }
-
调用
mavgTopN
计算滑动窗口内前几个元素的平均值# include "Swordfish.h" #include "OperatorImp.h" using namespace OperatorImp; int main() { DolphinDBLib::initializeRuntime(); // 构建待传入的参数 SessionSP session = DolphinDBLib::createSession(); VectorSP X = Util::createVector(DT_INT,0); std::vector<int> newData = {1, 2, 3, 4, 5, 6, 7}; X->appendInt(newData.data(), newData.size()); VectorSP S = Util::createVector(DT_DOUBLE,0); std::vector<double> newData1 = {0.3, 0.5, 0.1, 0.1, 0.5, 0.2, 0.4}; S->appendDouble(newData1.data(), newData1.size()); Int *window = new Int(4); Int *top = new Int(2); std::vector<ConstantSP> parameter = {X,S,window,top}; // 调用 mavgTopN 计算结果并打印 ConstantSP result = OperatorImp::mavgTopN(session->getHeap().get(),parameter); std::cout <<result->getString() << std::endl; DolphinDBLib::finalizeRuntime(); return 0; }
状态函数
Swordfish 定义了一系列状态函数,可以用于响应式状态引擎中。这些状态通过增量计算,优化了计算性能。本节以
createMsumReactiveState
为例,介绍如何创建一个移动求和的状态算子。实现流程如下:
-
创建 DolphinDB 会话,以便在会话中执行 DolphinDB 的内置函数。
-
创建状态表,用于存储 val 和 msum 的值。
-
创建参数数组 args,第一个参数为 val 列的引用,第二个参数为窗口长度 3,用于计算移动求和。
-
使用
ReactiveStateFactory::createMsumReactiveState
创建一个移动求和的状态算子msumReactiveState
。 -
向状态表中插入初始值(DBL_NMIN),表示移动求和的初始状态。
-
创建一个空的结果向量 msumResult,用于存储计算结果。
-
定义输入数据 valData,后续会对这些数值进行移动求和。
-
更新状态表,并调用
msumReactiveState->append()
方法进行增量计算。从状态表中获取当前索引的移动求和结果,并将其添加到结果向量 msumResult 中。 -
输出最终的移动求和结果。
#include "Swordfish.h"
int main() {
DolphinDBLib::initializeRuntime();
SessionSP session = DolphinDBLib::createSession();
// Calculate msum(val, 3) context by sym
vector<string> colNames = {"val", "msum"};
vector<DATA_TYPE> colTypes = { DT_DOUBLE, DT_DOUBLE};
TableSP stateTable = Util::createTable(colNames, colTypes, 0, 1);
vector<ObjectSP> args(2);
SQLContextSP context = new SQLContext();
args[0] = new ColumnRef(context, "val");
// Set window = 3
args[1] = new Int(3);
// Set input column index in stateTable
vector<int> inputColIndices = {0};
// Set input column data type in stateTable
vector<DATA_TYPE> inputColTypes = {DT_DOUBLE};
// Set output column index in stateTable
vector<int> outputColIndices = {1};
// Create msum reactive state
ReactiveStateSP msumReactiveState = ReactiveStateFactory::createMsumReactiveState(args, inputColIndices, inputColTypes, outputColIndices);
msumReactiveState->setTable(stateTable);
msumReactiveState->setSession(session);
context->setTable(stateTable);
INDEX rowInserted = 0;
string errMsg;
std::vector<ConstantSP> rowValues = {new Double(DBL_NMIN), new Double(DBL_NMIN)};
if(!stateTable->append(rowValues, rowInserted, errMsg)){
throw RuntimeException("Failed to append data to state table with error: " + errMsg);
}
msumReactiveState->addKeys(1);
// Create result VectorSP
VectorSP msumResult = Util::createVector(DT_DOUBLE, 0);
// Create input data
std::vector<double> valData = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};
INDEX rows = valData.size();
ConstantSP val = new Double();
std::vector<ConstantSP> updateValue = {val};
std::vector<string> updateColName = {"val"};
VectorSP index = Util::createIndexVector(0,1);
// Iterate through each element of valCol
for(int i = 0; i < rows; i++){
// Get the val element
val->setDouble(valData[i]);
if(!stateTable->update(updateValue, index, updateColName, errMsg)){
throw RuntimeException("Failed to update state table with error: " + errMsg);
}
// Incrementally calculate msum
msumReactiveState->append(session->getHeap().get(), index);
// Get the result from stateTable for the current index
ConstantSP res = stateTable->getColumn(1)->get(index);
msumResult->append(res);
}
std::cout<<" msum result"<<std::endl;
std::cout << msumResult->getString() << std::endl;
DolphinDBLib::finalizeRuntime();
return 0;
}