CLib 模块
CLib扩展,可以用来调用第三方动态库。
用CLib来加载一个第三方动态库
function loadLib()
{
var systemName = SystemName();
var libPath = GetRoot();
if(systemName == "windows")
{
libPath += "testdll.dll";
}
else if(systemName == "linux")
{
libPath += "libtestdll.so";
}
else
{
libPath += "libtestdll.dylib";
}
var clibs = new CLib(libPath);
if(!clibs.load())
{
print "load err!";
return 0;
}
print "load success!!";
}
CLib函数 | 描述 | 用法 |
---|---|---|
load() | 加载动态库 | clibs.load() |
free() | 释放动态库 | clibs.free() |
findFunc(funcName,returnType,parm1Type,……) | 获取导出函数,返回CLibFunc对象 | var tAdd = clibs.findFunc("tAdd","int","int","int"); |
CLibFunc函数 | 描述 | 用法 |
---|---|---|
callFunc(parm1,……) | 调用函数 | var res = tAdd.callFunc(100,300); |
例子
//c++函数定义
int tAdd(int a,int b)
{
return a + b;
}
import CBCLib.code
function main(parm)
{
var clibs = loadLib();
var tAdd = clibs.findFunc("tAdd","int","int","int");
var res = tAdd.callFunc(100,300);
print "tAdd : " + res;
}
结果:
tAdd : 400
与C++类型的对应关系
CLib类型 | c++类型 | 字节数 |
---|---|---|
"int" | int | 4 |
"float" | float | 4 |
"byte","char" | char | 1 |
"bool" | bool | 1 |
"short" | short | 2 |
"int64" | long long | 8 |
"double" | double | 8 |
"wchar" | wchar_t | windows:2。linux:4。macos:4 |
"string" | char | 64位OS:8。32位OS:4 |
"wstring" | wchar_t | 64位OS:8。32位OS:4 |
"pointer" | 任意类型指针 | 64位OS:8。32位OS:4 |
"callback" | 回调函数 | 64位OS:8。32位OS:4 |
例子2
//c++函数定义
const char* tTest(int a,int b,int c,float d,double e,float f,int g,int h,int i,long long j,int k,float l,double m,float n,float o)
{
char* buf = new char[4096];
memset(buf,0,4096);
sprintf(buf,"a=%d,b=%d,c=%d,d=%f,e=%lf,f=%f,g=%d,h=%d,i=%d,j=%ld,k=%d,l=%f,m=%lf,n=%f,o=%f",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o);
return buf;
}
void tfreeString(char* pStr)
{
delete[] pStr;
}
import CBCLib.code
function main(parm)
{
var clibs = loadLib();
var tTest = clibs.findFunc("tTest","string","int","int","int","float","double","float","int","int","int","int64","int","float","double","float","float");
var res = tTest.callFunc(1,2,3,4.0,5.0,6.0,7,8,9,10,11,12.0,13.0,14.0,15.0);
print "tTest : " + res; //虽然结果正确,但是内存泄漏了,对于需要释放的字符串不建议使用string接收
//应该以pointer方式接收被new出来的字符串
tTest = clibs.findFunc("tTest","pointer","int","int","int","float","double","float","int","int","int","int64","int","float","double","float","float");
res = tTest.callFunc(1,2,3,4.0,5.0,6.0,7,8,9,10,11,12.0,13.0,14.0,15.0);
print "tTest : " + res.readString();
var tfreeString = clibs.findFunc("tfreeString","void","pointer");
tfreeString.callFunc(res);
}
结果:
tTest : a=1,b=2,c=3,d=4.000000,e=5.000000,f=6.000000,g=7,h=8,i=9,j=10,k=11,l=12.000000,m=13.000000,n=14.000000,o=15.000000
tTest : a=1,b=2,c=3,d=4.000000,e=5.000000,f=6.000000,g=7,h=8,i=9,j=10,k=11,l=12.000000,m=13.000000,n=14.000000,o=15.000000
char*可以用"string"和"pointer"接收,区别在于,"string"会复制一份,"pointer"会保留原地址
用CLibPointer来操作内存
CLibPointer描述了一个内存地址。当函数返回值为"pointer"时返回该对象,也可以主动new出来操作内存。
CLibPointer函数 | 描述 | 用法 |
---|---|---|
addAddr(bytes) | 地址增加bytes字节 | ponter.addAddr(4); |
subAddr(bytes) | 地址减bytes字节 | ponter.subAddr(4); |
copyAddr() | 复制当前地址到一个新的指针对象中 | var newpoint = ponter.copyAddr(); |
malloc(bytes) | 申请地址空间,如果不是空指针,则调用无效果。 | ponter.malloc(4); |
free() | 释放内存空间 | ponter.free(); |
isNull() | 如果是空指针返回true,否则返回false | var isnull = ponter.isNull(); |
readString() | 从当前地址开始读取一个字符串,\0结束 | var str = ponter.readString(); |
readWString() | 从当前地址开始读取一个宽字符串,L'\0'结束 | var wstr = ponter.readWString(); |
readInt() | 从当前地址开始读取4个字节作为整数 | var intv = ponter.readInt(); |
readByte() | 从当前地址开始读取1个字节作为整数 | var intv = ponter.readByte(); |
readShort() | 从当前地址开始读取2个字节作为整数 | var intv = ponter.readShort(); |
readInt64() | 从当前地址开始读取8个字节作为整数 | var intv = ponter.readInt64(); |
readPointer() | 从当前地址开始读取一个地址,返回CLibPointer对象。32位OS读4个字节,64位OS读8个字节 | var newpoint = ponter.readPointer(); |
例子3
//c++函数定义
int* tTestIntArray(int &size)
{
size = 8;
int *a = new int[size];
for (int i = 0 ; i < size ; i++)
{
a[i] = i * 50;
}
return a;
}
void tFreeIntArray(int *a)
{
delete[] a;
}
import CBCLib.code
function main(parm)
{
var clibs = loadLib();
var tTestIntArray = clibs.findFunc("tTestIntArray","pointer","pointer");
//参数是一个引用,要提前申请空间
var intref = new CLibPointer();
intref.malloc(4);
var res = tTestIntArray.callFunc(intref);
//把值读出来
var intCount = intref.readInt();
print "tTestIntArray : intCount=>" + intCount;
print res;
var resRead = res.copyAddr(); //复制地址,因为读取后地址会自增,保留原地址要用来free
var resStr = "tTestIntArray : return=>\n";
for(var i = 0 ; i < intCount ; i++)
{
resStr += i + " " + resRead.readInt(true) + "\n";
}
print resStr;
intref.free(); //自己malloc的需要释放
var tFreeIntArray = clibs.findFunc("tFreeIntArray","pointer");
tFreeIntArray.callFunc(res);//c代码里new出来的,调用接口释放
}
结果:
tTestIntArray : intCount=>8
[CLibPointer]Object 0xfed220
tTestIntArray : return=>
0 0
1 50
2 100
3 150
4 200
5 250
6 300
7 350
用CLibStruct来定义结构体
//c++结构体定义
struct testStruct
{
int a;
int b;
float c;
double d;
char* e;
long long f;
short g;
char h;
bool i;
testStruct* self;
wchar_t* j;
};
#pragma pack(1)
struct testStruct2
{
int a;
char b;
short c;
};
//C++没有声明对其字节方式,一次写完参数类型即可
var structInfo_testStruct = new CLibStruct("int","int","float","double","string","int64","short","byte","bool","pointer","wstring");
//C++声明1字节对其,所以最后一个参数要写1
var structInfo_testStruct2 = new CLibStruct("int","char","short",1);
CLibStruct函数 | 描述 | 用法 |
---|---|---|
size() | 获取结构体的字节大小 | var s = structInfo.size() |
用CLibArray来定义数组
//c++结构体定义
struct testStruct2
{
testStruct test1;
//testStruct test2[2];
int test2[3];
long long test3[3];
short test4[3];
char test5[10];
float test6[3];
double test7[3];
char* test8[3];
bool test9[3];
testStruct* test10[3];
wchar_t* test11[3];
wchar_t test12[10];
};
var arrayInfo_int = new CLibArray("int",3);
var arrayInfo_int64 = new CLibArray("int64",3);
var arrayInfo_short = new CLibArray("short",3);
var arrayInfo_byte = new CLibArray("char",10);
var arrayInfo_float = new CLibArray("float",3);
var arrayInfo_double = new CLibArray("double",3);
var arrayInfo_string = new CLibArray("string",3);
var arrayInfo_bool = new CLibArray("bool",3);
var arrayInfo_pointer = new CLibArray("pointer",3);
var arrayInfo_wstring = new CLibArray("wstring",3);
var arrayInfo_wchar = new CLibArray("wchar",10);
//声明testStruct2结构体
var structInfo_testStruct2 = new CLibStruct(
structInfo_testStruct,
arrayInfo_int,
arrayInfo_int64,
arrayInfo_short,
arrayInfo_byte,
arrayInfo_float,
arrayInfo_double,
arrayInfo_string,
arrayInfo_bool,
arrayInfo_pointer,
arrayInfo_wstring,
arrayInfo_wchar);
用CLibStructData来读取结构体数据
CLibStruct是结构体的定义,CLibStructData是结构体的实例。
//构造testStruct结构体实例
var structData_test = new CLibStructData(structInfo_testStruct);
structData_test.setInt(0,90);
structData_test.setInt(1,100);
structData_test.setFloat(2,55.5);
structData_test.setFloat(3,555.5);
structData_test.setString(4,"2222222");
structData_test.setInt(5,200);
structData_test.setInt(6,230);
structData_test.setInt(7,199);
structData_test.setInt(8,1);
structData_test.setPointer(9,structData_test.addr()); //把自己的地址复制给自己的属性
print structData_test.getInt(0);
print structData_test.getInt(1);
print structData_test.getFloat(2);
print structData_test.getFloat(3);
print structData_test.getString(4);
print structData_test.getInt(5);
print structData_test.getInt(6);
print structData_test.getInt(7);
print structData_test.getBool(8);
CLibStructData函数 | 描述 | 用法 |
---|---|---|
addr() | 获取自身地址,返回CLibPointer对象 | var pointer = structData_test.addr(); |
getInt(idx) | 读取第idx个属性 | var intv = structData_test.getInt(idx); |
getInt64(idx) | 读取第idx个属性 | var int64v = structData_test.getInt64(idx); |
getBool(idx) | 读取第idx个属性 | var boolv = structData_test.getBool(idx); |
getFloat(idx) | 读取第idx个属性 | var floatv = structData_test.getFloat(idx); |
getString(idx) | 读取第idx个属性 | var str = structData_test.getString(idx); |
getWString(idx) | 读取第idx个属性 | var wstr = structData_test.getWString(idx); |
getPointer(idx) | 读取第idx个属性,返回CLibPointer | var pointer = structData_test.getPointer(idx); |
getStruct(idx) | 读取第idx个属性,返回CLibStructData | var pointer = structData_test.getStruct(idx); |
getArray(idx) | 读取第idx个属性,返回CLibArray | var array = structData_test.getArray(idx); |
setInt(idx,value) | 修改第idx个属性 | structData_test.setInt(idx,1); |
setInt64(idx,value) | 修改第idx个属性 | structData_test.setInt64(idx,1); |
setBool(idx,value) | 修改第idx个属性 | structData_test.setBool(idx,true); |
setFloat(idx,value) | 修改第idx个属性 | structData_test.setFloat(idx,1.0); |
setString(idx,value) | 修改第idx个属性 | structData_test.setString(idx,"1111"); |
setWString(idx,value) | 修改第idx个属性 | structData_test.setWString(idx,WSTRING("1111")); |
setPointer(idx,value) | 修改第idx个属性 | structData_test.setPointer(idx,pointer); |
setStruct(idx,value) | 修改第idx个属性 | structData_test.setStruct(idx,structData); |
setArray(idx,value) | 修改第idx个属性 | structData_test.setArray(idx,arrayData); |
setCallBack(idx,callback) | 修改第idx个属性为一个回调函数 | structData_test.setCallBack(idx,callback); |
例子4
//c++函数定义
testStruct* tGetStruct()
{
testStruct* ptestStruct = new testStruct;
ptestStruct->a = 50;
ptestStruct->b = -100;
return ptestStruct;
}
int tAddStruct(testStruct* ptestStruct)
{
return ptestStruct->a + ptestStruct->b;
}
void tfreeStruct(testStruct* ptestStruct)
{
delete ptestStruct;
}
import CBCLib.code
function main(parm)
{
var clibs = loadLib();
var tGetStruct = clibs.findFunc("tGetStruct","pointer");
var pStruct = tGetStruct.callFunc();
print pStruct;
var pStructData = new CLibStructData(structInfo_testStruct,pStruct);//用结构体指针构建一个结构体才可以访问内容
print pStructData.getInt(0);
print pStructData.getInt(1);
//int _STDCALL tAddStruct(testStruct* ptestStruct)
var tAddStruct = clibs.findFunc("tAddStruct","int","pointer");
var res = tAddStruct.callFunc(pStruct);
print "tAddStruct : " + res;
//c代码里new出来的,记得用c接口释放掉。
var tfreeStruct = clibs.findFunc("tfreeStruct","void","pointer");
tfreeStruct.callFunc(pStruct);
}
结果:
[CLibPointer]Object 0x10a54c0
50
-100
tAddStruct : -50
用CLibArrayData来读取数组
CLibArray是数组的定义,CLibArrayData是数组的实例。
var arrayData_int = new CLibArrayData(arrayInfo_int); //构建int test2[3];
arrayData_int.setInt(0,5000);
arrayData_int.setInt(1,6000);
arrayData_int.setInt(2,7000);
print arrayData_int.getInt(0);
print arrayData_int.getInt(1);
print arrayData_int.getInt(2);
CLibArray函数 | 描述 | 用法 |
---|---|---|
getInt(idx) | 读取数组第idx位的值 | var intv = arrayData.getInt(idx); |
getInt64(idx) | 读取数组第idx位的值 | var int64v = arrayData.getInt64(idx); |
getBool(idx) | 读取数组第idx位的值 | var boolv = arrayData.getBool(idx); |
getFloat(idx) | 读取数组第idx位的值 | var floatv = arrayData.getFloat(idx); |
getString(idx) | 读取数组第idx位的值 | var str = arrayData.getString(idx); |
getString() | 如果数组是char arr[xxx],可以按照string读取,前提是要有结束符 | var str = arrayData.getString(); |
getWString(idx) | 读取数组第idx位的值 | var wstr = arrayData.getWString(idx); |
getWString() | 如果数组是wchar_t arr[xxx],可以按照wstring读取,前提是要有结束符 | var wstr = arrayData.getWString(); |
getPointer(idx) | 读取数组第idx位的值,返回CLibPointer | var pointer = arrayData.getPointer(idx); |
getStruct(idx) | 读取数组第idx位的值,返回CLibStructData | var struct = arrayData.getStruct(idx); |
setInt(idx,value) | 修改数组第idx位的值 | arrayData.setInt(idx,1); |
setInt64(idx,value) | 修改数组第idx位的值 | arrayData.setInt64(idx,1); |
setBool(idx,value) | 修改数组第idx位的值 | arrayData.setBool(idx,true); |
setFloat(idx,value) | 修改数组第idx位的值 | arrayData.setFloat(idx,1.0); |
setString(idx,value) | 修改数组第idx位的值 | arrayData.setString(idx,"1111"); |
setString(value) | 如果数组是char arr[x],可以按照string修取 | arrayData.setString("1111"); |
setWString(idx,value) | 修改数组第idx位的值 | arrayData.setWString(idx,WSTRING("1111")); |
setWString(value) | 如果数组是wchar_t arr[x],可以按照wstring修取 | arrayData.setWString(WSTRING("1111")); |
setPointer(idx,value) | 修改数组第idx位的值 | arrayData.setPointer(idx,pointer); |
setStruct(idx,value) | 修改数组第idx位的值 | arrayData.setStruct(idx,structData); |
例子5
//c++函数定义
testStruct tGetStrcut2(testStruct test)
{
testStruct a;
a.a = 5;
a.b = 64;
return test;
}
testStruct2 tGetStrcut4(testStruct2 test)
{
int aaa = sizeof(testStruct2);
testStruct2 t;
t.test1.a = 5;
t.test1.b = 10;
t.test2[0] = 1000;
t.test2[1] = 2000;
t.test2[2] = 3000;
return test;
}
import CBCLib.code
function main(parm)
{
var clibs = loadLib();
var arrayData_int = new CLibArrayData(arrayInfo_int); //构建int test2[3];
arrayData_int.setInt(0,5000);
arrayData_int.setInt(1,6000);
arrayData_int.setInt(2,7000);
var arrayData_int64 = new CLibArrayData(arrayInfo_int64); //构建long long test3[3];
arrayData_int64.setInt(0,5001);
arrayData_int64.setInt(1,6001);
arrayData_int64.setInt(2,7001);
var arrayData_short = new CLibArrayData(arrayInfo_short); //构建short test4[3];
arrayData_short.setInt(0,100);
arrayData_short.setInt(1,200);
arrayData_short.setInt(2,300);
var arrayData_byte = new CLibArrayData(arrayInfo_byte); //构建char test5[10];
arrayData_byte.setInt(0,97);
arrayData_byte.setInt(1,98);
arrayData_byte.setInt(2,99);
//arrayData_byte.setString("abc"); //也可以设置一个字符串进去,上面三句等同于这一句
var arrayData_float = new CLibArrayData(arrayInfo_float); //构建float test6[3];
arrayData_float.setFloat(0,55.5);
arrayData_float.setFloat(1,66.6);
arrayData_float.setFloat(2,77.7);
var arrayData_double = new CLibArrayData(arrayInfo_double); //构建double test7[3];
arrayData_double.setFloat(0,555.55);
arrayData_double.setFloat(1,666.66);
arrayData_double.setFloat(2,777.77);
var arrayData_string = new CLibArrayData(arrayInfo_string); //构建char* test8[3];
arrayData_string.setString(0,"aaaaa");
arrayData_string.setString(1,"bbbbb");
arrayData_string.setString(2,"ccccc");
var arrayData_bool = new CLibArrayData(arrayInfo_bool); //构建bool test9[3];
arrayData_bool.setBool(0,true);
arrayData_bool.setBool(1,false);
arrayData_bool.setBool(2,true);
var arrayData_wstring = new CLibArrayData(arrayInfo_wstring); //构建wchar_t* test11[3];
arrayData_wstring.setWString(0,WSTRING("aaaaaaaa"));
arrayData_wstring.setWString(1,WSTRING("bbbbbbbb"));
arrayData_wstring.setWString(2,WSTRING("ccccccccc"));
var arrayData_wchar = new CLibArrayData(arrayInfo_wchar); //构建wchar_t test12[10];
arrayData_wchar.setInt(0,97);
arrayData_wchar.setInt(1,98);
arrayData_wchar.setInt(2,99);
//arrayData_wchar.setWString(WSTRING("abc")); //也可以设置一个字符串进去,上面三句等同于这一句
//构造testStruct结构体实例
var structData_test = new CLibStructData(structInfo_testStruct);
structData_test.setInt(0,90);
structData_test.setInt(1,100);
structData_test.setFloat(2,55.5);
structData_test.setFloat(3,555.5);
structData_test.setString(4,"2222222");
structData_test.setInt(5,200);
structData_test.setInt(6,230);
structData_test.setInt(7,199);
structData_test.setInt(8,1);
structData_test.setPointer(9,structData_test.addr());
structData_test.setWString(10,WSTRING("3333333"));
var tGetStrcut2 = clibs.findFunc("tGetStrcut2",structInfo_testStruct,structInfo_testStruct);
var res = tGetStrcut2.callFunc(structData_test);
var arrayData_pointer = new CLibArrayData(arrayInfo_pointer); //构建testStruct* test10[3];
arrayData_pointer.setPointer(0,res.addr());
arrayData_pointer.setPointer(2,structData_test.addr());
//构造testStruct2结构体实例
var structData_test2 = new CLibStructData(structInfo_testStruct2);
structData_test2.setStruct(0,res);
structData_test2.setArray(1,arrayData_int);
structData_test2.setArray(2,arrayData_int64);
structData_test2.setArray(3,arrayData_short);
structData_test2.setArray(4,arrayData_byte);
structData_test2.setArray(5,arrayData_float);
structData_test2.setArray(6,arrayData_double);
structData_test2.setArray(7,arrayData_string);
structData_test2.setArray(8,arrayData_bool);
structData_test2.setArray(9,arrayData_pointer);
structData_test2.setArray(10,arrayData_wstring);
structData_test2.setArray(11,arrayData_wchar);
//testStruct2 tGetStrcut4(testStruct2 test)
var tGetStrcut4 = clibs.findFunc("tGetStrcut4",structInfo_testStruct2,structInfo_testStruct2);
var res = tGetStrcut4.callFunc(structData_test2);
print res;
var struct = res.getStruct(0); //获取testStruct test1;
print struct;
print struct.getInt(0);
print struct.getInt(6);
var res_arraydata_int = res.getArray(1); //获取int test2[3];
print res_arraydata_int;
print res_arraydata_int.getInt(0);
print res_arraydata_int.getInt(1);
print res_arraydata_int.getInt(2);
var res_arraydata_int64 = res.getArray(2); //获取long long test3[3];
print res_arraydata_int64;
print res_arraydata_int64.getInt(0);
print res_arraydata_int64.getInt(1);
print res_arraydata_int64.getInt(2);
var res_arraydata_short = res.getArray(3); //获取short test4[3];
print res_arraydata_short;
print res_arraydata_short.getInt(0);
print res_arraydata_short.getInt(1);
print res_arraydata_short.getInt(2);
var res_arraydata_byte = res.getArray(4); //获取char test5[10];
print res_arraydata_byte;
print res_arraydata_byte.getInt(0);
print res_arraydata_byte.getInt(1);
print res_arraydata_byte.getInt(2);
print res_arraydata_byte.getInt(3);
print res_arraydata_byte.getString(); //如果char数组里是一个字符串,也可以只接拿字符串出来。如果没有结束符/0 可能会出现异常
var res_arraydata_float = res.getArray(5); //获取float test6[3];
print res_arraydata_float;
print res_arraydata_float.getFloat(0);
print res_arraydata_float.getFloat(1);
print res_arraydata_float.getFloat(2);
var res_arraydata_double = res.getArray(6); //获取double test7[3];
print res_arraydata_double;
print res_arraydata_double.getFloat(0);
print res_arraydata_double.getFloat(1);
print res_arraydata_double.getFloat(2);
var res_arraydata_string = res.getArray(7); //获取char* test8[3];
print res_arraydata_string;
print res_arraydata_string.getString(0);
print res_arraydata_string.getString(1);
print res_arraydata_string.getString(2);
var res_arraydata_bool = res.getArray(8); //获取bool test9[3];
print res_arraydata_bool;
print res_arraydata_bool.getBool(0);
print res_arraydata_bool.getBool(1);
print res_arraydata_bool.getBool(2);
var res_arraydata_pointer = res.getArray(9); //获取testStruct* test10[3];
print res_arraydata_pointer;
var res_arraydata_s_p = res_arraydata_pointer.getPointer(0);
print res_arraydata_s_p;
print res_arraydata_s_p.isNull();
var res_arrdata_pdata = new CLibStructData(structInfo_testStruct,res_arraydata_s_p);
print res_arrdata_pdata.getInt(1);
print res_arrdata_pdata.getFloat(2);
print res_arrdata_pdata.getPointer(9);
res_arraydata_s_p = res_arraydata_pointer.getPointer(1);
print res_arraydata_s_p;
print res_arraydata_s_p.isNull();
res_arrdata_pdata = new CLibStructData(structInfo_testStruct,res_arraydata_s_p);
print res_arrdata_pdata.getInt(1);
print res_arrdata_pdata.getFloat(2);
print res_arrdata_pdata.getPointer(9);
res_arraydata_s_p = res_arraydata_pointer.getPointer(2);
print res_arraydata_s_p;
print res_arraydata_s_p.isNull();
res_arrdata_pdata = new CLibStructData(structInfo_testStruct,res_arraydata_s_p);
print res_arrdata_pdata.getInt(1);
print res_arrdata_pdata.getFloat(2);
print res_arrdata_pdata.getPointer(9);
var res_arraydata_wstring = res.getArray(10); //获取wchar_t* test11[3];
print res_arraydata_wstring;
var wstring = res_arraydata_wstring.getWString(0);
print "wstring : " + wstring;
var utf8str = str_convert(wstring,"wstring","utf-8");
print "utf8str : " + utf8str;
var wstring = res_arraydata_wstring.getWString(1);
print "wstring : " + wstring;
var utf8str = str_convert(wstring,"wstring","utf-8");
print "utf8str : " + utf8str;
var wstring = res_arraydata_wstring.getWString(2);
print "wstring : " + wstring;
var utf8str = str_convert(wstring,"wstring","utf-8");
print "utf8str : " + utf8str;
var res_arraydata_wchar = res.getArray(11);
print res_arraydata_wchar;
print res_arraydata_wchar.getInt(0);
print res_arraydata_wchar.getInt(1);
print res_arraydata_wchar.getInt(2);
print res_arraydata_wchar.getInt(3);
var wstring = res_arraydata_wchar.getWString();
print "wstring : " + wstring;
var utf8str = str_convert(wstring,"wstring","utf-8");
print "utf8str : " + utf8str;
}
结果:
[CLibStructData]Object 0x10a6280
[CLibStructData]Object 0x10a62e0
90
230
[CLibArrayData]Object 0x10a6340
5000
6000
7000
[CLibArrayData]Object 0x10a63a0
5001
6001
7001
[CLibArrayData]Object 0x10a6400
100
200
300
[CLibArrayData]Object 0x10a6460
97
98
99
0
abc
[CLibArrayData]Object 0x10a64c0
55.500000
66.599998
77.699997
[CLibArrayData]Object 0x10a6520
555.549988
666.659973
777.770020
[CLibArrayData]Object 0x10a6580
aaaaa
bbbbb
ccccc
[CLibArrayData]Object 0x10a6700
true
false
true
[CLibArrayData]Object 0x10a6760
[CLibPointer]Object 0x10a67c0
false
100
55.500000
[CLibPointer]Object 0x10a6880
[CLibPointer]Object 0x10a68e0
true
0
0.000000
[CLibPointer]Object 0x10a69a0
[CLibPointer]Object 0x10a6a00
false
100
55.500000
[CLibPointer]Object 0x10a6ac0
[CLibArrayData]Object 0x10a6b20
wstring : a
utf8str : aaaaaaaa
wstring : b
utf8str : bbbbbbbb
wstring : c
utf8str : ccccccccc
[CLibArrayData]Object 0x10a6ee0
97
98
99
0
wstring : a
utf8str : abc
多维数组与一维数组在内存里完全相同,所以多维数组也按照一维数组处理。int[2][2]与int[4]相同,int[3][3][3]与int[27]相同。
回调函数
有时候第三方库的接口是传递一个回调函数,CBrother中使用CLibCallBack来实现这样的功能。
//c++函数定义
typedef int (*pCallBackFunc1)(float a,int b,int c,int d,double e,float f,int g,double h,int i,long long j,int k,float l,double m,float n,float o,float p);
typedef testStruct (*pCallBackFunc2)(testStruct a,testStruct *b);
//接收一个函数地址并回调回去
int tTestCallBack(void *func,const char* funcName)
{
if(strcmp(funcName,"CallBackFunc1") == 0)
{
pCallBackFunc1 pFunc = (pCallBackFunc1)func;
int res = pFunc(10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25);
return res;
}
else if(strcmp(funcName,"CallBackFunc2") == 0)
{
pCallBackFunc2 pFunc = (pCallBackFunc2)func;
testStruct s1,s2;
s1.a = 1;
s1.b = 2;
s1.c = 3;
s1.d = 4;
s1.e = "1111";
s1.f = 6;
s1.g = 7;
s1.h = 8;
s1.i = 9;
s1.j = L"2222";
s1.self = &s1;
s2.a = 10;
s2.b = 20;
s2.c = 30;
s2.d = 40;
s2.e = "11110";
s2.f = 60;
s2.g = 70;
s2.h = 80;
s2.i = 90;
s2.j = L"22220";
s2.self = &s2;
testStruct res = pFunc(s1,&s2);
if (res.a == s1.a)
{
return 1;
}
return 0;
}
}
调用例子1:
function CallBackFunc1(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)
{
print "CallBackFunc1 a=" + a
+ " b=" + b + " c=" + c + " d=" + d + " e=" + e + " f=" + f + " g=" + g + " h=" + h + " i=" + i
+ " j=" + j + " k=" + k + " l=" + l + " m=" + m + " n=" + n + " o=" + o + " p=" + p;
return 100;
}
function main()
{
var clibs = loadLib();
print "call_tTestCallBack1 begin";
//c++函数原形
var tTestCallBack = clibs.findFunc("tTestCallBack","int","callback","string");
//声明回调函数
var callback1 = new CLibCallBack(CallBackFunc1,"int","float","int","int","int","double","float","int","double",
"int","int64","int","float","double","float","float","float");
var res = tTestCallBack.callFunc(callback1,"CallBackFunc1");
print "call_tTestCallBack1 end " + res;
}
结果:
call_tTestCallBack1 begin
CallBackFunc1 a=10.000000 b=11 c=12 d=13 e=14.000000 f=15.000000 g=16 h=17.000000 i=18 j=19 k=20 l=2
1.000000 m=22.000000 n=23.000000 o=24.000000 p=25.000000
call_tTestCallBack1 end 100
调用例子2:
function CallBackFunc2(a,b)
{
print "CallBackFunc2 -------------------------------";
print a;
print a.getInt(0);
print a.getInt(1);
print a.getFloat(2);
print a.getFloat(3);
print a.getString(4);
print a.getInt(5);
print a.getInt(6);
print a.getInt(7);
print a.getBool(8);
var tPointerSelf = a.getPointer(9);
print tPointerSelf;
var pStructData_Self = new CLibStructData(structInfo_testStruct,tPointerSelf); //用结构体指针构建一个结构体才可以访问内容
print pStructData_Self.getInt(0);
print pStructData_Self.getString(4);
print pStructData_Self.getPointer(9);
return a;
}
function main()
{
var clibs = loadLib();
print "call_tTestCallBack2 begin";
//c++函数原形
var tTestCallBack = clibs.findFunc("tTestCallBack","int","callback","string");
//声明回调函数
var callback2 = new CLibCallBack(CallBackFunc2,structInfo_testStruct,structInfo_testStruct,"pointer");
var res = tTestCallBack.callFunc(callback2,"CallBackFunc2");
print "call_tTestCallBack2 end " + res;
}
结果:
call_tTestCallBack2 begin
CallBackFunc2 -------------------------------
[CLibStructData]Object 0xcc6a30
1
2
3.000000
4.000000
1111
6
7
8
true
[CLibPointer]Object 0xcc6b50
1
1111
[CLibPointer]Object 0xcc6c10
call_tTestCallBack2 end 1
CLibCallBack函数 | 描述 | 用法 |
---|---|---|
CLibCallBack(cbfunc,returnType,parm1Type,……,threadDel) | 构造函数,声明回调函数原形。最后一个参数为bool值,多数情况下不用写。 | var callback1 = new CLibCallBack(CallBackFunc1,"int","float","int","int") |
如果第三方库是在一个从未执行过CBrother代码的线程里调用回调函数,CBrother会自动为该线程创建CBrother运行时上下文,并不会自动销毁。 多数情况是在固定的几个线程里执行,这时不销毁就不用重复创建会提升执行效率。
但有些第三方库实现的糟糕,每次都是动态创建一个线程,执行完后再销毁线程,这时候CBrother的运行时上下文就需要销毁。 CLibCallBack的构造函数最后一个缺省参数为bool类型,默认是false,表示不销毁运行时环境,如果设置true则会销毁(销毁的前提是因为调用回调函数而创建了该运行时环境,如果该线程的运行时环境是其他地方创建的,此处便不会销毁)。
function main()
{
//这个回调函数不会销毁运行时
var callback = new CLibCallBack(CallBackFunc,"int","float","int","int");
//最后一个参数为true则会销毁
var callback = new CLibCallBack(CallBackFunc,"int","float","int","int",true);
}
支持的调用约定
64位程序调用约定已经统一,只要是64位程序都支持。
32位程序支持最常用的cdecl和stdcall。其他调用方式不支持。
总结
本章节的例子都在CBrother包的sample/clibs中。
CLib库提供了非常灵活的方式来操作内存,所以它是非安全的,也就是说稍不注意就会导致进程崩溃。再者,调用第三方动态库都需要遵守调用约定,如果你把结构体的成员类型或者函数的参数类型写错的话, 也是会崩溃的,因为你的这些错误CBrother没有办法帮你检查。
当你用到了CLib库,那么你一定要有能力去避免这些崩溃。