代码拉取完成,页面将自动刷新
同步操作将从 calvinwilliams/DirectStruct 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
DirectStruct - C结构体工具
1.概述
2.编译安装
3.基本使用
3.1.编写IDL定义文件,用自动化代码工具dsc处理之
3.2.编写应用代码,调用网络/主机字节序化函数
3.3.编写应用代码,调用二进制序列化/反序列化函数
3.4.编写应用代码,调用XML序列化/反序列化函数
3.5.编写应用代码,调用JSON序列化/反序列化函数
3.6.编写应用代码,使用ESQL代码开发数据库应用
N-2.DirectStruct报文定义文件语法
N-1.性能压测
N.最后
------------------------------------------------------------
1.概述
DirectStruct是一个强有力的代码自动生成工具,它可以自动生成C结构体与XML、JSON、二进制(带压缩)等报文之间的转换代码,还能自动生成ESQL代码片段,在应用中直接使用自动化代码以提高开发效率,避免开发冗余和手工编码风险。
DirectStruct生成了哪些自动化代码?
* C结构体定义
* 批量初始化缺省值函数
* 网络/主机字节序化函数
* 二进制序列化/反序列化函数(可带压缩)
* XML序列化/反序列化函数(展开风格和紧缩风格)(依赖开源库fasterxml[url]http://git.oschina.net/calvinwilliams/fasterxml[/url])
* JSON序列化/反序列化函数(展开风格和紧缩风格)(依赖开源库fasterjson[url]http://git.oschina.net/calvinwilliams/fasterjson[/url])
* 嵌入式SQL代码片段以及一些嵌入式SQL函数
* 打印结构体内所有字段值函数
用DirectStruct自动生成的代码能干什么?
* 直接C结构体通讯交换 : 在特定平台之间直接把C结构体变量通过TCP扔给对方是一个很诱人的想法,阻碍我们的主要是整型字段的字节序问题,手工编码是一件冗余的事情,DirectStruct可以帮助你自动化这一过程。解决了字节序问题后就可以直接交换报文,避免了通讯发送前的打包和通讯接收后的解包,所以速度非常快,是某些追求极端性能的场景中的首选报文格式。
* 结构体序列化/反序列化 : 使用DirectStruct自动生成的序列化/反序列化函数,可以将C结构体打包成二进制报文或XML报文或JSON报文等,以及反向解包,是的,打包解包函数自动生成,省却了你不少麻烦吧。二进制报文如果启用了压缩选项,压缩后的二进制数据块大幅缩小,更便于通讯高效交换。
* 基于嵌入式SQL的数据库映射接口的代码自动化生成
* 快速打印结构体内所有字段值 : 对于一个大结构,编写他的打印所有字段值的函数是一件很无聊的事情,你可以用DirectStruct帮助你自动生成日志函数,输出到屏幕,或你自己的日志流中。
* ( 新主意增加中 ... 把你的需求告诉我吧 )
为什么使用DirectStruct?
* 灵活的报文定义语法 : 命令行工具dsc读入定义文件,生成自动化代码,支持子结构嵌套、子结构数组、定义文件包含等灵活配置方式。
* 跨平台:DirectStruct支持WINDOWS、Linux、AIX等主流操作系统,尤其是多平台中不同的表达方法,如64位整型,相同的IDL定义文件将生成不同平台的标准。
2.编译安装
for Linux
$ tar xvzf dsc-1.1.0.tar.gz
$ cd dsc-1.1.0/src
$ su
# make -f makefile.Linux clean
rm -f util.o
rm -f main.o
rm -f dsc.o
rm -f ReadDscFile.o
rm -f GenerateCCode.o
rm -f dsc
# make -f makefile.Linux install
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I. -c util.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I. -c main.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I. -c dsc.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I. -c ReadDscFile.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I. -c GenerateCCode.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -o dsc util.o main.o dsc.o ReadDscFile.o GenerateCCode.o -L.
cp -f dsc /usr/bin/
3.基本使用
本章示例都取自于test目录中的测试程序。
3.1.编写IDL定义文件,用自动化代码工具dsc处理之
[code]
$ cat IDL_AllTypes.dsc
STRUCT AllTypes
{
# 这是注释
INT 1 n1 # 这也是注释
INT 2 n2
INT 4 n4
INT 8 n8
UINT 1 u1
UINT 2 u2
UINT 4 u4
UINT 8 u8
FLOAT 4 f4
FLOAT 8 f8
CHAR 1 ch
UCHAR 1 uch
STRING 32 str32
STRING 1024 str1024
}
$ dsc -f IDL_AllTypes.dsc -c-ALL
STRUCT AllTypes
INT 1 n1
INT 2 n2
INT 4 n4
INT 8 n8 # longlong or _int64 for c
UINT 1 u1
UINT 2 u2
UINT 4 u4
UINT 8 u8
FLOAT 4 f4
FLOAT 8 f8
CHAR 1 ch
UCHAR 1 uch
STRING 32 str32
STRING 1024 str1024
ok!
$ ls
IDL_AllTypes.dsc
IDL_AllTypes.dsc.h
IDL_AllTypes.dsc.c
IDL_AllTypes.dsc.LOG.c
[/code]
IDL_test.dsc.h包含了自动生成的一个C结构体定义。
IDL_test.dsc.c包含了自动生成的初始化缺省函数、网络/主机字节序化、序列化/反序列化等代码。
IDL_test.dsc.LOG.c包含了自动生成的一个日志函数用于快速打印报文所有字段到标准输出或你自己的日志流上便于调试。
注意:IDL_test.dsc.h、IDL_test.dsc.c实际内容取决于参数"-c-*"
[code]
$ dsc
dsc v1.1.0 - DirectSrtuct Compiler
Copyright by calvin<calvinwilliams.c@gmail.com> 2014
USAGE : dsc -f .dsc [ -c ] [ -c-order ] [ -c-compact ] [ -c-compress ] [ -c-xml ] [ -c-LOG ] [ -c-ALL ]
[/code]
-c 基本的c结构体定义
-c-order 还包含主机/网络字节序化函数
-c-compact 还包含二进制紧凑序列化/反序列化函数
-c-compress 还包含二进制压缩序列化/反序列化函数
-c-xml 还包含XML序列化/反序列化函数(依赖于开源库fastxml)
-c-LOG 生成IDL_test.dsc.LOG.c
-c-ALL 生成以上所有
注意:test/makefile未包含处理.dsc定义文件的动作,如修改.dsc文件后需要手工处理之。
3.2.编写应用代码,调用网络/主机字节序化函数
[code]
$ cat test_netorder.c
int test_netorder()
{
AllTypes st ;
int nret = 0 ;
/* client code */
memset( & st , 0x00 , sizeof(AllTypes) );
st.n1 = -0x11 ;
st.n2 = -0x1122 ;
st.n4 = -0x11223344 ;
st.n8 = LL(-0x1122334455667788) ;
st.u1 = 0x11 ;
st.u2 = 0x1122 ;
st.u4 = 0x11223344 ;
st.u8 = ULL(0x1122334455667788) ;
st.f4 = 100.00 ;
st.f8 = 10000.00 ;
st.ch = 'A' ;
st.uch = 'B' ;
strcpy( st.str32 , "calvin" );
strcpy( st.str1024 , "XXXXXXXXXXXXXXXX" );
DSCLOG_AllTypes( & st );
nret = DSCNETORDER_AllTypes( & st ) ;
if( nret )
{
printf( "DSCNETORDER_AllTypes failed[%d]\n" , nret );
return nret;
}
else
{
printf( "DSCNETORDER_AllTypes ok\n" );
}
/* ... client send communication struct to server ... */
/* server code */
nret = DSCHOSTORDER_AllTypes( & st ) ;
if( nret )
{
printf( "DSCHOSTORDER_AllTypes failed[%d]\n" , nret );
return nret;
}
else
{
printf( "DSCHOSTORDER_AllTypes ok\n" );
}
DSCLOG_AllTypes( & st );
return 0;
}
$ make -f makefile.Linux
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I. -c test_netorder.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I. -c IDL_AllTypes.dsc.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -o test_netorder test_netorder.o IDL_AllTypes.dsc.o -L.
$ ./test_netorder
AllTypes.n1[-17]
AllTypes.n2[-4386]
AllTypes.n4[-287454020]
AllTypes.n8[-1234605616436508552]
AllTypes.u1[17]
AllTypes.u2[4386]
AllTypes.u4[287454020]
AllTypes.u8[1234605616436508552]
AllTypes.f4[100.000000]
AllTypes.f8[10000.000000]
AllTypes.ch[A]
AllTypes.uch[B]
AllTypes.str32[calvin]
AllTypes.str1024[XXXXXXXXXXXXXXXX]
DSCNETORDER_AllTypes ok
0x0000000000 ef 00 ee de ee dd cc bc ee dd cc bb aa 99 88 78 ...............x
0x0000000001 11 00 11 22 11 22 33 44 11 22 33 44 55 66 77 88 ..."."3D."3DUfw.
0x0000000002 00 00 c8 42 00 00 00 00 00 88 c3 40 41 42 63 61 ...B.......@ABca
0x0000000003 6c 76 69 6e 00 00 00 00 00 00 00 00 00 00 00 00 lvin............
0x0000000004 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 58 ...............X
0x0000000005 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 00 XXXXXXXXXXXXXXX.
...
DSCHOSTORDER_AllTypes ok
AllTypes.n1[-17]
AllTypes.n2[-4386]
AllTypes.n4[-287454020]
AllTypes.n8[-1234605616436508552]
AllTypes.u1[17]
AllTypes.u2[4386]
AllTypes.u4[287454020]
AllTypes.u8[1234605616436508552]
AllTypes.f4[100.000000]
AllTypes.f8[10000.000000]
AllTypes.ch[A]
AllTypes.uch[B]
AllTypes.str32[calvin]
AllTypes.str1024[XXXXXXXXXXXXXXXX]
[/code]
3.3.编写应用代码,调用二进制序列化/反序列化函数
[code]
$ cat test_serialize_compact.c
int test_serialize_compact()
{
AllTypes st ;
char buf[ DSCSERIALIZE_COMPACT_BUFSIZE_AllTypes + 1 ] ;
int len ;
int nret = 0 ;
/* client code */
memset( & st , 0x00 , sizeof(AllTypes) );
st.n1 = -0x11 ;
st.n2 = -0x1122 ;
st.n4 = -0x11223344 ;
st.n8 = LL(-0x1122334455667788) ;
st.u1 = 0x11 ;
st.u2 = 0x1122 ;
st.u4 = 0x11223344 ;
st.u8 = ULL(0x1122334455667788) ;
st.f4 = 100.00 ;
st.f8 = 10000.00 ;
st.ch = 'A' ;
st.uch = 'B' ;
strcpy( st.str32 , "calvin" );
strcpy( st.str1024 , "XXXXXXXXXXXXXXXX" );
memset( buf , 0x00 , sizeof(buf) );
nret = DSCSERIALIZE_COMPACT_AllTypes( & st , buf , & len ) ;
if( nret )
{
printf( "DSCSERIALIZE_COMPACT_AllTypes failed[%d]\n" , nret );
return nret;
}
else
{
printf( "DSCSERIALIZE_COMPACT_AllTypes ok , len[%d]\n" , len );
}
dump( buf , len );
/* ... client send communication struct to server ... */
/* server code */
memset( & st , 0x00 , sizeof(AllTypes) );
nret = DSCDESERIALIZE_COMPACT_AllTypes( buf , & len , & st ) ;
if( nret )
{
printf( "DSCDESERIALIZE_COMPACT_AllTypes failed[%d]\n" , nret );
return nret;
}
else
{
printf( "DSCDESERIALIZE_COMPACT_AllTypes ok\n" );
}
DSCLOG_AllTypes( & st );
return 0;
}
$ make -f makefile.Linux
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I. -c test_netorder.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I. -c test_serialize_compact.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -o test_serialize_compact test_serialize_compact.o IDL_AllTypes.dsc.o -L.
$ ./test_serialize_compact
DSCSERIALIZE_COMPACT_AllTypes ok , len[1100]
0x0000000000 ef ee de ee dd cc bc ee dd cc bb aa 99 88 78 11 ..............x.
0x0000000001 11 22 11 22 33 44 11 22 33 44 55 66 77 88 00 00 ."."3D."3DUfw...
0x0000000002 c8 42 00 00 00 00 00 88 c3 40 41 42 63 61 6c 76 .B.......@ABcalv
0x0000000003 69 6e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 in..............
0x0000000004 00 00 00 00 00 00 00 00 00 00 00 00 58 58 58 58 ............XXXX
0x0000000005 58 58 58 58 58 58 58 58 58 58 58 58 00 00 00 00 XXXXXXXXXXXX....
...
DSCDESERIALIZE_COMPACT_AllTypes ok
AllTypes.n1[-17]
AllTypes.n2[-4386]
AllTypes.n4[-287454020]
AllTypes.n8[-1234605616436508552]
AllTypes.u1[17]
AllTypes.u2[4386]
AllTypes.u4[287454020]
AllTypes.u8[1234605616436508552]
AllTypes.f4[100.000000]
AllTypes.f8[10000.000000]
AllTypes.ch[A]
AllTypes.uch[B]
AllTypes.str32[calvin]
AllTypes.str1024[XXXXXXXXXXXXXXXX]
[/code]
紧凑(COMPACT)序列化的内部原理是把所有字段值在内存中的映像平铺在一个大数据块中,首尾相接,无填充空间,且整型值做字节序处理。如
STRUCT struct_name
{
INT 4 n4
STRING 256 str256
}
序列化后的布局为
n4(4字节)+str256(256字节)
总共260字节
使用带压缩的序列化函数可以使得最终二进制数据块更小
[code]
$ cat test_serialize_compress.c
...
int test_serialize_compress()
{
AllTypes st ;
char buf[ DSCSERIALIZE_COMPRESS_BUFSIZE_AllTypes + 1 ] ;
int len ;
int nret = 0 ;
/* client code */
memset( & st , 0x00 , sizeof(AllTypes) );
st.n1 = -0x11 ;
st.n2 = -0x1122 ;
st.n4 = -0x11223344 ;
st.n8 = LL(-0x1122334455667788) ;
st.u1 = 0x11 ;
st.u2 = 0x1122 ;
st.u4 = 0x11223344 ;
st.u8 = ULL(0x1122334455667788) ;
st.f4 = 100.00 ;
st.f8 = 10000.00 ;
st.ch = 'A' ;
st.uch = 'B' ;
strcpy( st.str32 , "calvin" );
strcpy( st.str1024 , "XXXXXXXXXXXXXXXX" );
DSCLOG_AllTypes( & st );
memset( buf , 0x00 , sizeof(buf) );
nret = DSCSERIALIZE_COMPRESS_AllTypes( & st , buf , & len ) ;
if( nret )
{
printf( "DSCSERIALIZE_COMPRESS_AllTypes failed[%d]\n" , nret );
return nret;
}
else
{
printf( "DSCSERIALIZE_COMPRESS_AllTypes ok , len[%d]\n" , len );
}
dump( buf , len );
/* ... client send communication struct to server ... */
/* server code */
memset( & st , 0x00 , sizeof(AllTypes) );
nret = DSCDESERIALIZE_COMPRESS_AllTypes( buf , & len , & st ) ;
if( nret )
{
printf( "DSCDESERIALIZE_COMPRESS_AllTypes failed[%d]\n" , nret );
return nret;
}
else
{
printf( "DSCDESERIALIZE_COMPRESS_AllTypes ok\n" );
}
DSCLOG_AllTypes( & st );
return 0;
}
...
$ make -f makefile.Linux
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I. -c test_netorder.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I. -c test_serialize_compress.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -o test_serialize_compress test_serialize_compress.o IDL_AllTypes.dsc.o -L.
$ ./test_serialize_compress
AllTypes.n1[-17]
AllTypes.n2[-4386]
AllTypes.n4[-287454020]
AllTypes.n8[-1234605616436508552]
AllTypes.u1[17]
AllTypes.u2[4386]
AllTypes.u4[287454020]
AllTypes.u8[1234605616436508552]
AllTypes.f4[100.000000]
AllTypes.f8[10000.000000]
AllTypes.ch[A]
AllTypes.uch[B]
AllTypes.str32[calvin]
AllTypes.str1024[XXXXXXXXXXXXXXXX]
DSCSERIALIZE_COMPRESS_AllTypes ok , len[74]
0x0000000000 ef ee de 14 11 22 33 44 18 11 22 33 44 55 66 77 ....."3D.."3DUfw
0x0000000001 88 11 11 22 04 11 22 33 44 08 11 22 33 44 55 66 ...".."3D.."3DUf
0x0000000002 77 88 00 00 c8 42 00 00 00 00 00 88 c3 40 41 42 w....B.......@AB
0x0000000003 01 06 63 61 6c 76 69 6e 01 10 58 58 58 58 58 58 ..calvin..XXXXXX
0x0000000004 58 58 58 58 58 58 58 58 58 58 XXXXXXXXXX
DSCDESERIALIZE_COMPRESS_AllTypes ok
AllTypes.n1[-17]
AllTypes.n2[-4386]
AllTypes.n4[-287454020]
AllTypes.n8[-1234605616436508552]
AllTypes.u1[17]
AllTypes.u2[4386]
AllTypes.u4[287454020]
AllTypes.u8[1234605616436508552]
AllTypes.f4[100.000000]
AllTypes.f8[10000.000000]
AllTypes.ch[A]
AllTypes.uch[B]
AllTypes.str32[calvin]
AllTypes.str1024[XXXXXXXXXXXXXXXX]
[/code]
这个示例中不压缩的二进制数据块有1100字节,压缩后只有74字节,适用于网络数据交换。
压缩(COMPRESS)序列化的内部原理是在紧凑序列化的基础上对某些类型的字段做压缩转换处理。
INT 4类型放置前置头字节,左四位为选项,目前只用到了正负数标志(正数为0,负数为1),右四位为实际存储长度,如某值的网络字节序为0x00001234,实际存储为0x1234,加上前置头,总共用3字节表达
0x02 0x12 0x34
值-0x1234也是用3字节表达
0x12 0x12 0x34
INT 8类同
UINT类型INT
STRING n类型放置前置UINT 4字段记录长度。如"abc",实际长度为3字节,前置UINT 4字段0x01 0x03,总共用5字节表达
0x01 0x03 0x61 0x62 0x63
其它字段类型不压缩转换
如
STRUCT struct_name
{
INT 4 n4
STRING 256 str256
}
当
n4=0x3456
str256="abc"
压缩序列化后的数据为
0x02 0x34 0x56 0x01 0x05 0x61 0x62 0x63
总共8字节,看,是不是比紧凑序列化要短的多呢,这在通讯数据交换中可以节省更多的流量。
3.4.编写应用代码,调用XML序列化/反序列化函数
XML序列化/反序列化函数依赖于开源库fasterxml。
[code]
$ cat test_serialize_xml.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "IDL_BankXmlTransaction.dsc.h"
#include "IDL_BankXmlTransaction.dsc.LOG.c"
int test_serialize_xml()
{
BankXmlTransaction trans ;
char buf[ 40960 + 1 ] ;
int len ;
int nret = 0 ;
/* client code */
DSCINIT_BankXmlTransaction( & trans );
strcpy( trans.ResponseHeader.transaction_code , "P0101" );
trans.ResponseHeader.trans_jnlsno = 12345678 ;
trans.ResponseHeader.response_code = 0 ;
strcpy( trans.ResponseHeader.response_desc , "OK" );
strcpy( trans.QueryTransactionDetails.AddonMessages.AddonMessage[1].message_text , "Check channel passed" );
strcpy( trans.QueryTransactionDetails.AddonMessages.AddonMessage[0].message_text , "Check account passed" );
strcpy( trans.QueryTransactionDetails.TransactionDetailTitle.title_text , "DETAIL TITLE" );
trans.QueryTransactionDetails.TransactionDetailTitle.page_no = 1 ;
trans.QueryTransactionDetails.TransactionDetailTitle.page_size = 2 ;
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[0].trans_date , "2014-01-01" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[0].trans_time , "08:01:01" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[0].outlet_id , "1001" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[0].card_no , "603367123412341234" );
trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[0].trans_amount = 100.00 ;
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[1].trans_date , "2014-02-02" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[1].trans_time , "08:02:02" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[1].outlet_id , "2002" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[1].card_no , "603367123412341234" );
trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[1].trans_amount = 200.00 ;
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[2].card_no , "<" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[3].card_no , "&" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[4].card_no , ">" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[5].card_no , "<&>" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[6].card_no , "<你&他>" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[7].card_no , "我<你&他>她" );
DSCLOG_BankXmlTransaction( & trans );
memset( buf , 0x00 , sizeof(buf) );
len = sizeof(buf)-1 ;
nret = DSCSERIALIZE_XML_BankXmlTransaction( & trans , "GBK" , buf , & len ) ;
if( nret )
{
printf( "DSCSERIALIZE_XML_BankXmlTransaction failed[%d]\n" , nret );
return nret;
}
else
{
printf( "DSCSERIALIZE_XML_BankXmlTransaction ok , len[%d]\n" , len );
}
printf( "[%s]\n" , buf );
/* ... client send communication struct to server ... */
/* server code */
memset( & trans , 0x00 , sizeof(BankXmlTransaction) );
nret = DSCDESERIALIZE_XML_BankXmlTransaction( NULL , buf , & len , & trans ) ;
if( nret )
{
printf( "DSCDESERIALIZE_XML_BankXmlTransaction failed[%d]\n" , nret );
return nret;
}
else
{
printf( "DSCDESERIALIZE_XML_BankXmlTransaction ok\n" );
}
DSCLOG_BankXmlTransaction( & trans );
return 0;
}
int main()
{
return -test_serialize_xml();
}
$ make
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I. -c test_serialize_xml.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I/home/calvin/exinc/fastxml -I. -c IDL_BankXmlTransaction.dsc.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -o test_serialize_xml test_serialize_xml.o IDL_BankXmlTransaction.dsc.o -L. -L/home/calvin/exlib -lfastxl
$ ./test_serialize_xml
BankXmlTransaction.version[1]
BankXmlTransaction.ResponseHeader.transaction_code[P0101]
BankXmlTransaction.ResponseHeader.trans_jnlsno[12345678]
BankXmlTransaction.ResponseHeader.response_code[0]
BankXmlTransaction.ResponseHeader.response_desc[OK]
BankXmlTransaction.QueryTransactionDetails.AddonMessages.AddonMessage[index[3]].message_text[Check account passed]
BankXmlTransaction.QueryTransactionDetails.AddonMessages.AddonMessage[index[3]].message_text[Check channel passed]
BankXmlTransaction.QueryTransactionDetails.AddonMessages.AddonMessage[index[3]].message_text[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetailTitle.title_text[DETAIL TITLE]
BankXmlTransaction.QueryTransactionDetails.TransactionDetailTitle.page_no[1]
BankXmlTransaction.QueryTransactionDetails.TransactionDetailTitle.page_size[2]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[2014-01-01]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[08:01:01]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[1001]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[603367123412341234]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[100.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[2014-02-02]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[08:02:02]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[2002]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[603367123412341234]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[200.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[<]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[&]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[>]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[<&>]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[<你&他>]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[我<你&他>她]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
DSCSERIALIZE_XML_BankXmlTransaction ok , len[2734]
[<?xml version="1.0" encoding="GBK"?>
<BankXmlTransaction>
<version>1</version>
<ResponseHeader>
<transaction_code>P0101</transaction_code>
<trans_jnlsno>12345678</trans_jnlsno>
<response_code>0</response_code>
<response_desc>OK</response_desc>
</ResponseHeader>
<QueryTransactionDetails>
<AddonMessages>
<AddonMessage>
<message_text>Check account passed</message_text>
</AddonMessage>
<AddonMessage>
<message_text>Check channel passed</message_text>
</AddonMessage>
<AddonMessage>
<message_text></message_text>
</AddonMessage>
</AddonMessages>
<TransactionDetailTitle>
<title_text>DETAIL TITLE</title_text>
<page_no>1</page_no>
<page_size>2</page_size>
</TransactionDetailTitle>
<TransactionDetails>
<TransactionDetail>
<trans_date>2014-01-01</trans_date>
<trans_time>08:01:01</trans_time>
<outlet_id>1001</outlet_id>
<card_no>603367123412341234</card_no>
<trans_amount>100.000000</trans_amount>
</TransactionDetail>
<TransactionDetail>
<trans_date>2014-02-02</trans_date>
<trans_time>08:02:02</trans_time>
<outlet_id>2002</outlet_id>
<card_no>603367123412341234</card_no>
<trans_amount>200.000000</trans_amount>
</TransactionDetail>
<TransactionDetail>
<trans_date></trans_date>
<trans_time></trans_time>
<outlet_id></outlet_id>
<card_no><</card_no>
<trans_amount>0.000000</trans_amount>
</TransactionDetail>
<TransactionDetail>
<trans_date></trans_date>
<trans_time></trans_time>
<outlet_id></outlet_id>
<card_no>&</card_no>
<trans_amount>0.000000</trans_amount>
</TransactionDetail>
<TransactionDetail>
<trans_date></trans_date>
<trans_time></trans_time>
<outlet_id></outlet_id>
<card_no>></card_no>
<trans_amount>0.000000</trans_amount>
</TransactionDetail>
<TransactionDetail>
<trans_date></trans_date>
<trans_time></trans_time>
<outlet_id></outlet_id>
<card_no><&></card_no>
<trans_amount>0.000000</trans_amount>
</TransactionDetail>
<TransactionDetail>
<trans_date></trans_date>
<trans_time></trans_time>
<outlet_id></outlet_id>
<card_no><你&他></card_no>
<trans_amount>0.000000</trans_amount>
</TransactionDetail>
<TransactionDetail>
<trans_date></trans_date>
<trans_time></trans_time>
<outlet_id></outlet_id>
<card_no>我<你&他>她</card_no>
<trans_amount>0.000000</trans_amount>
</TransactionDetail>
<TransactionDetail>
<trans_date></trans_date>
<trans_time></trans_time>
<outlet_id></outlet_id>
<card_no></card_no>
<trans_amount>0.000000</trans_amount>
</TransactionDetail>
<TransactionDetail>
<trans_date></trans_date>
<trans_time></trans_time>
<outlet_id></outlet_id>
<card_no></card_no>
<trans_amount>0.000000</trans_amount>
</TransactionDetail>
</TransactionDetails>
</QueryTransactionDetails>
</BankXmlTransaction>
]
DSCDESERIALIZE_XML_BankXmlTransaction ok
BankXmlTransaction.version[1]
BankXmlTransaction.ResponseHeader.transaction_code[P0101]
BankXmlTransaction.ResponseHeader.trans_jnlsno[12345678]
BankXmlTransaction.ResponseHeader.response_code[0]
BankXmlTransaction.ResponseHeader.response_desc[OK]
BankXmlTransaction.QueryTransactionDetails.AddonMessages.AddonMessage[index[3]].message_text[Check account passed]
BankXmlTransaction.QueryTransactionDetails.AddonMessages.AddonMessage[index[3]].message_text[Check channel passed]
BankXmlTransaction.QueryTransactionDetails.AddonMessages.AddonMessage[index[3]].message_text[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetailTitle.title_text[DETAIL TITLE]
BankXmlTransaction.QueryTransactionDetails.TransactionDetailTitle.page_no[1]
BankXmlTransaction.QueryTransactionDetails.TransactionDetailTitle.page_size[2]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[2014-01-01]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[08:01:01]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[1001]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[603367123412341234]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[100.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[2014-02-02]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[08:02:02]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[2002]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[603367123412341234]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[200.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[<]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[&]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[>]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[<&>]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[<你&他>]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[我<你&他>她]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[]
BankXmlTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
[/code]
3.5.编写应用代码,调用JSON序列化/反序列化函数
JSON序列化/反序列化函数依赖于开源库fasterjson。
[code]
$ cat test_serialize_json.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "IDL_BankJsonTransaction.dsc.h"
#include "IDL_BankJsonTransaction.dsc.LOG.c"
int test_serialize_json()
{
BankJsonTransaction trans ;
char buf[ 40960 + 1 ] ;
int len ;
int nret = 0 ;
/* client code */
DSCINIT_BankJsonTransaction( & trans );
strcpy( trans.ResponseHeader.transaction_code , "P0101" );
trans.ResponseHeader.trans_jnlsno = 12345678 ;
trans.ResponseHeader.response_code = 0 ;
strcpy( trans.ResponseHeader.response_desc , "OK" );
strcpy( trans.QueryTransactionDetails.AddonMessages.AddonMessage[1].message_text , "Check channel passed" );
strcpy( trans.QueryTransactionDetails.AddonMessages.AddonMessage[0].message_text , "Check account passed" );
strcpy( trans.QueryTransactionDetails.TransactionDetailTitle.title_text , "DETAIL TITLE" );
trans.QueryTransactionDetails.TransactionDetailTitle.page_no = 1 ;
trans.QueryTransactionDetails.TransactionDetailTitle.page_size = 2 ;
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[0].trans_date , "2014-01-01" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[0].trans_time , "08:01:01" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[0].outlet_id , "1001" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[0].card_no , "603367123412341234" );
trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[0].trans_amount = 100.00 ;
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[1].trans_date , "2014-02-02" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[1].trans_time , "08:02:02" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[1].outlet_id , "2002" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[1].card_no , "603367123412341234" );
trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[1].trans_amount = 200.00 ;
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[2].card_no , "\"" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[3].card_no , "\"你\"他\"" );
strcpy( trans.QueryTransactionDetails.TransactionDetails.TransactionDetail[4].card_no , "我\"你\"他\"她" );
DSCLOG_BankJsonTransaction( & trans );
memset( buf , 0x00 , sizeof(buf) );
len = sizeof(buf)-1 ;
nret = DSCSERIALIZE_JSON_BankJsonTransaction( & trans , "GBK" , buf , & len ) ;
if( nret )
{
printf( "DSCSERIALIZE_JSON_BankJsonTransaction failed[%d]\n" , nret );
return nret;
}
else
{
printf( "DSCSERIALIZE_JSON_BankJsonTransaction ok , len[%d]\n" , len );
}
printf( "[%s]\n" , buf );
/* ... client send communication struct to server ... */
/* server code */
memset( & trans , 0x00 , sizeof(BankJsonTransaction) );
nret = DSCDESERIALIZE_JSON_BankJsonTransaction( NULL , buf , & len , & trans ) ;
if( nret )
{
printf( "DSCDESERIALIZE_JSON_BankJsonTransaction failed[%d]\n" , nret );
return nret;
}
else
{
printf( "DSCDESERIALIZE_JSON_BankJsonTransaction ok\n" );
}
DSCLOG_BankJsonTransaction( & trans );
return 0;
}
int main()
{
return -test_serialize_json();
}
$ make
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I. -I/home/calvin/exinc/fasterxml -I/home/calvin/exinc/fasterjson -c test_serialize_json.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -o test_serialize_json test_serialize_json.o IDL_BankJsonTransaction.dsc.o -L. -L/home/calvin/exlib -lfasterjson
$ ./test_serialize_json
BankJsonTransaction.version[1]
BankJsonTransaction.ResponseHeader.transaction_code[P0101]
BankJsonTransaction.ResponseHeader.trans_jnlsno[12345678]
BankJsonTransaction.ResponseHeader.response_code[0]
BankJsonTransaction.ResponseHeader.response_desc[OK]
BankJsonTransaction.QueryTransactionDetails.AddonMessages.AddonMessage[index[3]].message_text[Check account passed]
BankJsonTransaction.QueryTransactionDetails.AddonMessages.AddonMessage[index[3]].message_text[Check channel passed]
BankJsonTransaction.QueryTransactionDetails.AddonMessages.AddonMessage[index[3]].message_text[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetailTitle.title_text[DETAIL TITLE]
BankJsonTransaction.QueryTransactionDetails.TransactionDetailTitle.page_no[1]
BankJsonTransaction.QueryTransactionDetails.TransactionDetailTitle.page_size[2]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[2014-01-01]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[08:01:01]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[1001]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[603367123412341234]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[100.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[2014-02-02]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[08:02:02]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[2002]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[603367123412341234]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[200.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no["]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no["你"他"]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[我"你"他"她]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionTailDetail[index[3]].message_text[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionTailDetail[index[3]].message_text[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionTailDetail[index[3]].message_text[]
DSCSERIALIZE_JSON_BankJsonTransaction ok , len[2330]
[{
"BankJsonTransaction" :
{
"version" : 1 ,
"ResponseHeader" :
{
"transaction_code" : "P0101" ,
"trans_jnlsno" : 12345678 ,
"response_code" : 0 ,
"response_desc" : "OK"
} ,
"QueryTransactionDetails" :
{
"AddonMessages" :
{
"AddonMessage" :
[
{
"message_text" : "Check account passed"
} ,
{
"message_text" : "Check channel passed"
} ,
{
"message_text" : ""
}
]
} ,
"TransactionDetailTitle" :
{
"title_text" : "DETAIL TITLE" ,
"page_no" : 1 ,
"page_size" : 2
} ,
"TransactionDetails" :
{
"TransactionDetail" :
[
{
"trans_date" : "2014-01-01" ,
"trans_time" : "08:01:01" ,
"outlet_id" : "1001" ,
"card_no" : "603367123412341234" ,
"trans_amount" : 100.000000
} ,
{
"trans_date" : "2014-02-02" ,
"trans_time" : "08:02:02" ,
"outlet_id" : "2002" ,
"card_no" : "603367123412341234" ,
"trans_amount" : 200.000000
} ,
{
"trans_date" : "" ,
"trans_time" : "" ,
"outlet_id" : "" ,
"card_no" : "\"" ,
"trans_amount" : 0.000000
} ,
{
"trans_date" : "" ,
"trans_time" : "" ,
"outlet_id" : "" ,
"card_no" : "\"你\"他\"" ,
"trans_amount" : 0.000000
} ,
{
"trans_date" : "" ,
"trans_time" : "" ,
"outlet_id" : "" ,
"card_no" : "我\"你\"他\"她" ,
"trans_amount" : 0.000000
} ,
{
"trans_date" : "" ,
"trans_time" : "" ,
"outlet_id" : "" ,
"card_no" : "" ,
"trans_amount" : 0.000000
} ,
{
"trans_date" : "" ,
"trans_time" : "" ,
"outlet_id" : "" ,
"card_no" : "" ,
"trans_amount" : 0.000000
} ,
{
"trans_date" : "" ,
"trans_time" : "" ,
"outlet_id" : "" ,
"card_no" : "" ,
"trans_amount" : 0.000000
} ,
{
"trans_date" : "" ,
"trans_time" : "" ,
"outlet_id" : "" ,
"card_no" : "" ,
"trans_amount" : 0.000000
} ,
{
"trans_date" : "" ,
"trans_time" : "" ,
"outlet_id" : "" ,
"card_no" : "" ,
"trans_amount" : 0.000000
}
] ,
"TransactionTailDetail" :
[
{
"message_text" : ""
} ,
{
"message_text" : ""
} ,
{
"message_text" : ""
}
]
}
}
}
}
]
DSCDESERIALIZE_JSON_BankJsonTransaction ok
BankJsonTransaction.version[1]
BankJsonTransaction.ResponseHeader.transaction_code[P0101]
BankJsonTransaction.ResponseHeader.trans_jnlsno[12345678]
BankJsonTransaction.ResponseHeader.response_code[0]
BankJsonTransaction.ResponseHeader.response_desc[OK]
BankJsonTransaction.QueryTransactionDetails.AddonMessages.AddonMessage[index[3]].message_text[Check account passed]
BankJsonTransaction.QueryTransactionDetails.AddonMessages.AddonMessage[index[3]].message_text[Check channel passed]
BankJsonTransaction.QueryTransactionDetails.AddonMessages.AddonMessage[index[3]].message_text[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetailTitle.title_text[DETAIL TITLE]
BankJsonTransaction.QueryTransactionDetails.TransactionDetailTitle.page_no[1]
BankJsonTransaction.QueryTransactionDetails.TransactionDetailTitle.page_size[2]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[2014-01-01]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[08:01:01]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[1001]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[603367123412341234]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[100.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[2014-02-02]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[08:02:02]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[2002]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[603367123412341234]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[200.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no["]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no["你"他"]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[我"你"他"她]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_date[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_time[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].outlet_id[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].card_no[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionDetail[index[3]].trans_amount[0.000000]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionTailDetail[index[3]].message_text[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionTailDetail[index[3]].message_text[]
BankJsonTransaction.QueryTransactionDetails.TransactionDetails.TransactionTailDetail[index[3]].message_text[]
[/code]
3.6.编写应用代码,使用ESQL代码开发数据库应用
[code]
$ cat IDL_testable.dsc
STRUCT testable
{
INT 2 n2
INT 4 n4
FLOAT 4 f4
FLOAT 8 f8
STRING 32 str32
STRING 1024 str1024
CREATE_SQL "CREATE INDEX testable_idx1 ON testable ( n2 ) ;"
CREATE_SQL "CREATE UNIQUE INDEX testable_idx2 ON testable ( str32 , str1024 ) ;"
DROP_SQL "DROP INDEX testable_idx1 ;"
DROP_SQL "DROP INDEX testable_idx2 ;"
}
$ dsc -f IDL_testable.dsc -sql -ec-pqsql -c-LOG
STRUCT testable
INT 2 n2
INT 4 n4
FLOAT 4 f4
FLOAT 8 f8
STRING 32 str32
STRING 1024 str1024
ok!
$ ls IDL_testable.dsc*
IDL_testable.dsc IDL_testable.dsc.ESQL.ec IDL_testable.dsc.ESQL.eh IDL_testable.dsc.LOG.c IDL_testable.dsc.create.sql IDL_testable.dsc.h
IDL_testable.dsc.ESQL.c IDL_testable.dsc.ESQL.ecE IDL_testable.dsc.ESQL.o IDL_testable.dsc.c IDL_testable.dsc.drop.sql
$ cat IDL_testable.dsc.create.sql
-- It had generated by DirectStruct v1.1.2
CREATE TABLE testable
(
n2 SMALLINT ,
n4 INTEGER ,
f4 REAL ,
f8 DOUBLE PRECISION ,
str32 CHARACTER VARYING(32) ,
str1024 CHARACTER VARYING(1024)
) ;
CREATE INDEX testable_idx1 ON testable ( n2 ) ;
CREATE UNIQUE INDEX testable_idx2 ON testable ( str32 , str1024 ) ;
$ ... run IDL_testable.dsc.create.sql in your database ...
$ cat test_testable.ec
#include "IDL_testable.dsc.ESQL.eh"
#include "IDL_testable.dsc.LOG.c"
int test_delete()
{
EXEC SQL
DELETE
FROM testable
WHERE n2 IN ( 100 , 101 , 102 ) ;
if( SQLCODE == 100 )
{
printf( "DELETE ok\n" );
}
else if( SQLCODE )
{
printf( "DELETE failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return SQLCODE;
}
else
{
printf( "DELETE ok\n" );
}
return 0;
}
int test_insert()
{
testable t ;
memset( & t , 0x00 , sizeof(testable) );
t.n2 = 100 ;
t.n4 = 56789 ;
t.f4 = 1.2 ;
t.f8 = 456.789 ;
strcpy( t.str32 , "hi" );
strcpy( t.str1024 , "hello world" );
DSCINITV_testable();
DSCSTOV_testable( & t );
EXEC SQL
INSERT
INTO testable
VALUES ( DBVLIST_testable ) ;
if( SQLCODE )
{
printf( "INSERT failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return SQLCODE;
}
else
{
printf( "INSERT ok\n" );
}
memset( & t , 0x00 , sizeof(testable) );
t.n2 = 101 ;
t.n4 = 56789 ;
t.f4 = 1.2 ;
t.f8 = 456.789 ;
strcpy( t.str32 , "hi" );
strcpy( t.str1024 , "hello earth" );
DSCINITV_testable();
DSCSTOV_testable( & t );
EXEC SQL
INSERT
INTO testable
VALUES ( DBVLIST_testable ) ;
if( SQLCODE )
{
printf( "INSERT failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return SQLCODE;
}
else
{
printf( "INSERT ok\n" );
}
memset( & t , 0x00 , sizeof(testable) );
t.n2 = 102 ;
t.n4 = 56789 ;
t.f4 = 1.2 ;
t.f8 = 456.789 ;
strcpy( t.str32 , "hi" );
strcpy( t.str1024 , "hello march" );
DSCINITV_testable();
DSCSTOV_testable( & t );
EXEC SQL
INSERT
INTO testable
VALUES ( DBVLIST_testable ) ;
if( SQLCODE )
{
printf( "INSERT failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return SQLCODE;
}
else
{
printf( "INSERT ok\n" );
}
return 0;
}
int test_update()
{
testable t ;
memset( & t , 0x00 , sizeof(testable) );
t.n2 = 101 ;
DSCINITV_testable();
DSCSTOV_testable( & t );
EXEC SQL
SELECT TFLIST_testable
INTO DBVLLIST_testable
FROM testable
WHERE n2 = :testable_n2 ;
if( SQLCODE )
{
printf( "SELECT failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return SQLCODE;
}
else
{
printf( "SELECT ok\n" );
}
DSCVTOS_testable( & t );
strcpy( t.str1024 , "hello sun" );
DSCINITV_testable();
DSCSTOV_testable( & t );
EXEC SQL
UPDATE testable
SET str1024 = :testable_str1024
WHERE n2 = :testable_n2 ;
if( SQLCODE )
{
printf( "UPDATE failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return SQLCODE;
}
else
{
printf( "UPDATE ok\n" );
}
return 0;
}
int test_cursor()
{
testable t ;
int nret = 0 ;
EXEC SQL
DECLARE testable_cursor CURSOR FOR
SELECT TFLIST_testable
FROM testable
ORDER BY n2 ASC ;
if( SQLCODE )
{
printf( "DECLARE failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return SQLCODE;
}
else
{
printf( "DECLARE ok\n" );
}
EXEC SQL
OPEN testable_cursor ;
if( SQLCODE )
{
printf( "OPEN failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return SQLCODE;
}
else
{
printf( "OPEN ok\n" );
}
while(1)
{
EXEC SQL
FETCH testable_cursor
INTO DBVLLIST_testable ;
if( SQLCODE == 100 )
{
break;
}
else if( SQLCODE )
{
printf( "FETCH failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
nret = SQLCODE ;
}
else
{
printf( "FETCH ok\n" );
}
memset( & t , 0x00 , sizeof(testable) );
DSCVTOS_testable( & t );
DSCLOG_testable( & t );
}
EXEC SQL
CLOSE testable_cursor ;
if( SQLCODE )
{
printf( "CLOSE failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return SQLCODE;
}
else
{
printf( "CLOSE ok\n" );
}
if( nret )
return nret;
return 0;
}
EXEC SQL BEGIN DECLARE SECTION ;
char sql[] = "DELETE FROM testable WHERE n2 = 102 ;" ;
EXEC SQL END DECLARE SECTION ;
int test_immediate()
{
EXEC SQL
EXECUTE IMMEDIATE :sql ;
if( SQLCODE )
{
printf( "EXECUTE failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return SQLCODE;
}
else
{
printf( "EXECUTE ok\n" );
}
return 0;
}
EXEC SQL BEGIN DECLARE SECTION ;
char sql2[] = "SELECT * FROM testable WHERE n2 >= ? ;" ;
EXEC SQL END DECLARE SECTION ;
int test_prepare()
{
testable t ;
int nret = 0 ;
EXEC SQL
PREPARE prepare FROM :sql2 ;
if( SQLCODE )
{
printf( "PREPARE failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return SQLCODE;
}
else
{
printf( "PREPARE ok\n" );
}
testable_n2 = 101 ;
EXEC SQL
EXECUTE prepare
INTO DBVLLIST_testable
USING :testable_n2 ;
if( SQLCODE )
{
printf( "EXECUTE failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return SQLCODE;
}
else
{
printf( "EXECUTE ok\n" );
}
memset( & t , 0x00 , sizeof(testable) );
DSCVTOS_testable( & t );
DSCLOG_testable( & t );
testable_n2 = 100 ;
EXEC SQL
DECLARE testable_cursor2 CURSOR FOR prepare ;
if( SQLCODE )
{
printf( "DECLARE failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return SQLCODE;
}
else
{
printf( "DECLARE ok\n" );
}
EXEC SQL
OPEN testable_cursor2
USING :testable_n2 ;
if( SQLCODE )
{
printf( "OPEN failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return SQLCODE;
}
else
{
printf( "OPEN ok\n" );
}
while(1)
{
EXEC SQL
FETCH testable_cursor2
INTO DBVLLIST_testable ;
if( SQLCODE == 100 )
{
break;
}
else if( SQLCODE )
{
printf( "FETCH failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
nret = SQLCODE ;
}
else
{
printf( "FETCH ok\n" );
}
memset( & t , 0x00 , sizeof(testable) );
DSCVTOS_testable( & t );
DSCLOG_testable( & t );
}
EXEC SQL
CLOSE testable_cursor2 ;
if( SQLCODE )
{
printf( "CLOSE failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return SQLCODE;
}
else
{
printf( "CLOSE ok\n" );
}
if( nret )
return nret;
EXEC SQL
DEALLOCATE PREPARE prepare ;
return 0;
}
int main()
{
int nret = 0 ;
EXEC SQL
CONNECT TO 'calvin@127.0.0.1:18432'
USER 'calvin'
IDENTIFIED BY 'calvin' ;
if( SQLCODE )
{
printf( "CONNECT failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return 1;
}
else
{
printf( "CONNECT ok\n" );
}
EXEC SQL
BEGIN WORK ;
if( SQLCODE )
{
printf( "BEGIN WORK failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return 1;
}
else
{
printf( "BEGIN WORK ok\n" );
}
do
{
printf( "--- delete ---------\n" );
nret = test_delete() ;
if( nret )
break;
printf( "--- insert ---------\n" );
nret = test_insert() ;
if( nret )
break;
printf( "--- update ---------\n" );
nret = test_update() ;
if( nret )
break;
printf( "--- cursor ---------\n" );
nret = test_cursor() ;
if( nret )
break;
printf( "--- immediate ---------\n" );
nret = test_immediate() ;
if( nret )
break;
printf( "--- prepare ---------\n" );
nret = test_prepare() ;
if( nret )
break;
}
while(0);
if( nret )
{
EXEC SQL
ROLLBACK WORK ;
if( SQLCODE )
{
printf( "ROLLBACK WORK failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return 1;
}
else
{
printf( "ROLLBACK WORK ok\n" );
}
}
else
{
EXEC SQL
COMMIT WORK ;
if( SQLCODE )
{
printf( "COMMIT WORK failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return 1;
}
else
{
printf( "COMMIT WORK ok\n" );
}
}
EXEC SQL
DISCONNECT ;
if( SQLCODE )
{
printf( "DISCONNECT failed[%ld][%s]\n" , SQLCODE , SQLSTATE );
return 1;
}
else
{
printf( "DISCONNECT ok\n" );
}
return 0;
}
$ make
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I/root/local/postgresql/include -E -x c IDL_testable.dsc.ESQL.ec > IDL_testable.dsc.ESQL.ecE # c预处理
ecpg -h IDL_testable.dsc.ESQL.ecE -o IDL_testable.dsc.ESQL.c # postgresql esql预处理器处理之
sed -i 's/NULL/0/g' IDL_testable.dsc.ESQL.c # 去掉ecpg加上的pqsql头文件,防止重复包含错误
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I/root/local/postgresql/include -c IDL_testable.dsc.ESQL.c # 最后的编译
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I/root/local/postgresql/include -E -x c test_testable.ec > test_testable.ecE
ecpg -h test_testable.ecE -o test_testable.c
sed -i 's/NULL/0/g' test_testable.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I/root/local/postgresql/include -c test_testable.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -o test_testable IDL_testable.dsc.ESQL.o test_testable.o -L. -L/root/local/postgresql/lib -lecpg
$ ./test_testable
CONNECT ok
BEGIN WORK ok
--- delete ---------
DELETE ok
--- insert ---------
INSERT ok
INSERT ok
INSERT ok
--- update ---------
SELECT ok
UPDATE ok
--- cursor ---------
DECLARE ok
OPEN ok
FETCH ok
testable.n2[100]
testable.n4[56789]
testable.f4[1.200000]
testable.f8[456.789000]
testable.str32[hi]
testable.str1024[hello world]
FETCH ok
testable.n2[101]
testable.n4[56789]
testable.f4[1.200000]
testable.f8[456.789000]
testable.str32[hi]
testable.str1024[hello sun]
FETCH ok
testable.n2[102]
testable.n4[56789]
testable.f4[1.200000]
testable.f8[456.789000]
testable.str32[hi]
testable.str1024[hello march]
CLOSE ok
--- immediate ---------
EXECUTE ok
--- prepare ---------
PREPARE ok
EXECUTE ok
testable.n2[101]
testable.n4[56789]
testable.f4[1.200000]
testable.f8[456.789000]
testable.str32[hi]
testable.str1024[hello sun]
DECLARE ok
OPEN ok
FETCH ok
testable.n2[100]
testable.n4[56789]
testable.f4[1.200000]
testable.f8[456.789000]
testable.str32[hi]
testable.str1024[hello world]
FETCH ok
testable.n2[101]
testable.n4[56789]
testable.f4[1.200000]
testable.f8[456.789000]
testable.str32[hi]
testable.str1024[hello sun]
CLOSE ok
COMMIT WORK ok
DISCONNECT ok
[/code]
在dsc文件中还可以使用SQLACTION指令自动生成一些ESQL函数,语法如下:
SQLACTION "SELECT ... FROM 表名 [ WHERE ... ]"
SQLACTION "INSERT INTO 表名"
SQLACTION "UPDATE 表名 SET ... [ WHERE ... ]"
SQLACTION "DELETE FROM 表名 [ WHERE ... ]"
SQLACTION "CURSOR 游标名 SELECT ... FROM 表名 [ WHERE ... ] [ ORDER BY ... [DESC|ASC] ]"
示例如下:
[code]
$ cat IDL_userinfo.dsc
STRUCT userinfo
{
INT 4 user_id DEFAULT 1 NOTNULL
STRING 16 user_name DEFAULT '0000'
STRING 128 email NULL
CREATE_SQL "CREATE UNIQUE INDEX userinfo_idx1 ON userinfo ( user_id ) ;"
DROP_SQL "DROP INDEX testable_idx1 ;"
SQLACTION "SELECT user_name,email FROM userinfo WHERE user_id ="
SQLACTION "SELECT * FROM userinfo WHERE user_id = AND user_name ="
SQLACTION "INSERT INTO userinfo"
SQLACTION "UPDATE userinfo SET * WHERE user_id ="
SQLACTION "UPDATE userinfo SET email"
SQLACTION "DELETE FROM userinfo WHERE user_id >="
SQLACTION "DELETE FROM userinfo"
SQLACTION "CURSOR mycursor SELECT * FROM userinfo"
SQLACTION "CURSOR mycursor1 SELECT user_name FROM userinfo WHERE user_id >="
SQLACTION "CURSOR mycursor2 SELECT user_name,email FROM userinfo ORDER BY user_id ASC"
SQLACTION "CURSOR mycursor3 SELECT * FROM userinfo WHERE user_id >= ORDER BY user_id ASC"
}
$ dsc -f IDL_userinfo.dsc -sql -ec-pqsql
...
$ cat IDL_userinfo.dsc.ESQL.ec
...
void DSCSQLACTION_SELECT_user_name_email_FROM_userinfo_WHERE_user_id_E( userinfo *pst )
{
DSCSTOV_userinfo( pst );
EXEC SQL
SELECT user_name,email
INTO :userinfo_user_name :userinfo_user_name_id , :userinfo_email :userinfo_email_id
FROM userinfo
WHERE user_id = :userinfo_user_id
;
if( SQLCODE )
return;
DSCVTOS_userinfo( pst );
return;
}
void DSCSQLACTION_SELECT_A_FROM_userinfo_WHERE_user_id_E_AND_user_name_E( userinfo *pst )
{
DSCSTOV_userinfo( pst );
EXEC SQL
SELECT *
INTO DBVLLIST_userinfo
FROM userinfo
WHERE user_id = :userinfo_user_id AND user_name = :userinfo_user_name
;
if( SQLCODE )
return;
DSCVTOS_userinfo( pst );
return;
}
void DSCSQLACTION_INSERT_INTO_userinfo( userinfo *pst )
{
DSCSTOV_userinfo( pst );
EXEC SQL
INSERT INTO userinfo
VALUES ( DBVLLIST_userinfo )
;
return;
}
void DSCSQLACTION_UPDATE_userinfo_SET_A_WHERE_user_id_E( userinfo *pst )
{
DSCSTOV_userinfo( pst );
EXEC SQL
UPDATE userinfo
SET ( TFLIST_userinfo ) = ( DBVLIST_userinfo )
WHERE user_id = :userinfo_user_id
;
return;
}
void DSCSQLACTION_UPDATE_userinfo_SET_email( userinfo *pst )
{
DSCSTOV_userinfo( pst );
EXEC SQL
UPDATE userinfo
SET email = :userinfo_email
;
return;
}
void DSCSQLACTION_DELETE_FROM_userinfo_WHERE_user_id_GE( userinfo *pst )
{
DSCSTOV_userinfo( pst );
EXEC SQL
DELETE
FROM userinfo
WHERE user_id >= :userinfo_user_id
;
return;
}
void DSCSQLACTION_DELETE_FROM_userinfo( userinfo *pst )
{
DSCSTOV_userinfo( pst );
EXEC SQL
DELETE
FROM userinfo
;
return;
}
void DSCSQLACTION_OPEN_CURSOR_mycursor_SELECT_A_FROM_userinfo( userinfo *pst )
{
EXEC SQL
DECLARE userinfo_mycursor CURSOR FOR
SELECT *
FROM userinfo
;
if( SQLCODE )
return;
EXEC SQL
OPEN userinfo_mycursor
; if( SQLCODE )
return;
return;
}
void DSCSQLACTION_FETCH_CURSOR_mycursor( userinfo *pst )
{
EXEC SQL
FETCH userinfo_mycursor
INTO DBVLLIST_userinfo
;
if( SQLCODE )
return;
DSCVTOS_userinfo( pst );
return;
}
void DSCSQLACTION_CLOSE_CURSOR_mycursor()
{
EXEC SQL
CLOSE userinfo_mycursor
;
return;
}
void DSCSQLACTION_OPEN_CURSOR_mycursor1_SELECT_user_name_FROM_userinfo_WHERE_user_id_GE( userinfo *pst )
{
EXEC SQL
DECLARE userinfo_mycursor1 CURSOR FOR
SELECT user_name
FROM userinfo
WHERE user_id >= :userinfo_user_id
;
if( SQLCODE )
return;
EXEC SQL
OPEN userinfo_mycursor1
; if( SQLCODE )
return;
return;
}
void DSCSQLACTION_FETCH_CURSOR_mycursor1( userinfo *pst )
{
EXEC SQL
FETCH userinfo_mycursor1
INTO :userinfo_user_name :userinfo_user_name_id
;
if( SQLCODE )
return;
DSCVTOS_userinfo( pst );
return;
}
void DSCSQLACTION_CLOSE_CURSOR_mycursor1()
{
EXEC SQL
CLOSE userinfo_mycursor1
;
return;
}
void DSCSQLACTION_OPEN_CURSOR_mycursor2_SELECT_user_name_email_FROM_userinfo_ORDER_BY_user_id_ASC( userinfo *pst )
{
EXEC SQL
DECLARE userinfo_mycursor2 CURSOR FOR
SELECT user_name,email
FROM userinfo
ORDER BY user_id ASC
;
if( SQLCODE )
return;
EXEC SQL
OPEN userinfo_mycursor2
; if( SQLCODE )
return;
return;
}
void DSCSQLACTION_FETCH_CURSOR_mycursor2( userinfo *pst )
{
EXEC SQL
FETCH userinfo_mycursor2
INTO :userinfo_user_name :userinfo_user_name_id, :userinfo_email :userinfo_email_id
;
if( SQLCODE )
return;
DSCVTOS_userinfo( pst );
return;
}
void DSCSQLACTION_CLOSE_CURSOR_mycursor2()
{
EXEC SQL
CLOSE userinfo_mycursor2
;
return;
}
void DSCSQLACTION_OPEN_CURSOR_mycursor3_SELECT_A_FROM_userinfo_WHERE_user_id_GE_ORDER_BY_user_id_ASC( userinfo *pst )
{
EXEC SQL
DECLARE userinfo_mycursor3 CURSOR FOR
SELECT *
FROM userinfo
WHERE user_id >= :userinfo_user_id
ORDER BY user_id ASC
;
if( SQLCODE )
return;
EXEC SQL
OPEN userinfo_mycursor3
; if( SQLCODE )
return;
return;
}
void DSCSQLACTION_FETCH_CURSOR_mycursor3( userinfo *pst )
{
EXEC SQL
FETCH userinfo_mycursor3
INTO DBVLLIST_userinfo
;
if( SQLCODE )
return;
DSCVTOS_userinfo( pst );
return;
}
void DSCSQLACTION_CLOSE_CURSOR_mycursor3()
{
EXEC SQL
CLOSE userinfo_mycursor3
;
return;
}
...
[/code]
可以在你的代码中直接调用这些函数,而不用手工编码了。
还能根据不同数据库自动生成各自的连接数据库、断开数据库、事务开始、事务提交、事务回滚等函数,只要加上SQLCONN指令即可
N-2.DirectStruct报文定义文件语法
每个结构或内嵌子结构定义格式都以
[code]
STRUCT 结构名 ARRAY 数组数量
{
...
}
[/code]
囊括,其中首行的ARRAY及后是可选的
每个字段定义行格式为
[code]
字段类型 字段长度 字段名 DEFAULT 缺省值
[/code]
其中字段类型及长度目前支持
INT 1,2,4,8 ( 8位至64位整型 )
UINT 1,2,4,8
FLOAT 4,8
CHAR 1
UCHAR 1
STRING (N)
DEFAULT及后是可选的
任何行位置可以用
[code]
INCLUDE 文件名
[/code]
引用其它.dsc文件
下面是一个综合的例子:
[code]
$ cat IDL_BankTransaction.dsc
STRUCT BankTransaction
{
INT 1 version DEFAULT 1
INCLUDE IDL_ResponseHeader.dsc
STRUCT QueryTransactionDetails
{
STRUCT AddonMessages ARRAY 3
{
STRING 64 message_text
}
STRUCT TransactionDetailTitle
{
STRING 64 title_text
INT 2 page_no
INT 2 page_size
}
STRUCT TransactionDetails ARRAY 10
{
STRING 10 trans_date
STRING 10 trans_time
STRING 6 outlet_id
STRING 20 card_no
FLOAT 4 trans_amount
}
}
}
$ cat IDL_ResponseHeader.dsc
STRUCT ResponseHeader
{
STRING 32 transaction_code
INT 4 trans_jnlsno
INT 4 response_code DEFAULT 0
STRING 1024 response_desc DEFAULT "OK"
}
[/code]
附加说明:DEFAULT后面的缺省值,由自动化生成的函数DSCINIT_BankTransaction批量初始化。
N-1.性能压测
在高性能场合中,数据序列化和反序列化效率很关键,其中主要考察最终报文大小和序列化速度。
同时,我们还拿了Google公司大名鼎鼎的Protocol Buffer来做对比实验。
压测环境:
CPU : Intel(R) Core(TM) i3-3240 CPU 3.4GHz/3.4GHz
内存 : 2GB
操作系统 : WINDOWS XP SP3 ( VMWare 6.0.1 ( Red Hat Enterprise Linux Server release 5.4 ) )
压测版本:
DirectStruct-1.0.3
protobuf-2.3.0
压测报文结构:
DirectStruct
[code]
$ cat IDL_AllTypes2.dsc
STRUCT AllTypes2
{
INT 4 n4
INT 8 n8
UINT 4 u4
UINT 8 u8
FLOAT 4 f4
FLOAT 8 f8
STRING 32 str32
STRING 1024 str1024
}
$ dsc -f IDL_AllTypes2.dsc -c
$ ls
IDL_AllTypes2.dsc.c IDL_AllTypes2.dsc.h
[/code]
Google Protocol Buffer
[code]
$ cat PressProtobuf.proto
message PressProtobuf
{
required sint32 n4 = 2 ;
required sint64 n8 =3 ;
required int32 un4 = 5 ;
required int64 un8 = 6 ;
required float f4 = 7 ;
required double f8 = 8 ;
required string str32 = 9 ;
required string str1024 = 10 ;
}
$ protoc -I=. --cpp_out=. PressProtobuf.proto
$ ls
PressProtobuf.pb.cc PressProtobuf.pb.h
[/code]
压测代码:
DirectStruct
[code]
$ cat test/test_serialize_compress_press.c
...
int test_serialize_compress_press( long count )
{
AllTypes2 st ;
char buf[ DSCSERIALIZE_COMPRESS_BUFSIZE_AllTypes2 + 1 ] ;
int len ;
long c ;
long t1 , t2 , dt ;
int nret = 0 ;
memset( & st , 0x00 , sizeof(AllTypes2) );
st.n4 = -0x11223344 ;
st.n8 = LL(-0x1122334455667788) ;
st.u4 = 0x11223344 ;
st.u8 = ULL(0x1122334455667788) ;
st.f4 = 100.00 ;
st.f8 = 10000.00 ;
strcpy( st.str32 , "calvin" );
strcpy( st.str1024 , "XXXXXXXXXXXXXXXX" );
DSCLOG_AllTypes2( & st );
printf( "Press begin\n" );
time( & t1 );
for( c = 0 ; c < count ; c++ )
{
memset( buf , 0x00 , sizeof(buf) );
nret = DSCSERIALIZE_COMPRESS_AllTypes2( & st , buf , & len ) ;
if( nret )
{
printf( "DSCSERIALIZE_COMPRESS_AllTypes2 failed[%d]\n" , nret );
return nret;
}
memset( & st , 0x00 , sizeof(AllTypes2) );
nret = DSCDESERIALIZE_COMPRESS_AllTypes2( buf , & len , & st ) ;
if( nret )
{
printf( "DSCDESERIALIZE_COMPRESS_AllTypes2 failed[%d]\n" , nret );
return nret;
}
}
printf( "Press end\n" );
time( & t2 );
dt = t2 - t1 ;
printf( "data compress size[%d] - compact size[%d]\n" , len , DSCSERIALIZE_COMPACT_BUFSIZE_AllTypes2 );
printf( "Elapse %ld seconds\n" , dt );
dump( buf , len );
DSCLOG_AllTypes2( & st );
return 0;
}
...
$ make -f makefile
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I. -c IDL_AllTypes2.dsc.c
gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I. -c test_serialize_compress_press.c
gcc -o test_serialize_compress_press test_serialize_compress_press.o IDL_AllTypes2.dsc.o -L.
[/code]
Google Protocol Buffer
[code]
$ cat test_protobuf/test_protobuf_press.cc
...
int test_protobuf_press( int count )
{
PressProtobuf press ;
PressProtobuf press2 ;
string str ;
int len ;
int c ;
press.set_n4( -0x11223344 );
press.set_n8( -0x1122334455667788LL );
press.set_un4( 0x11223344 );
press.set_un8( 0x1122334455667788LL );
press.set_f4( 100.00 );
press.set_f8( 10000.00 );
press.set_str32( "calvin" );
press.set_str1024( "XXXXXXXXXXXXXXXX" );
printf( "[%d]\n" , press.n4() );
printf( "[%lld]\n" , press.n8() );
printf( "[%d]\n" , press.un4() );
printf( "[%lld]\n" , press.un8() );
printf( "[%f]\n" , press.f4() );
printf( "[%lf]\n" , press.f8() );
printf( "[%s]\n" , press.str32().c_str() );
printf( "[%s]\n" , press.str1024().c_str() );
for( c = 0 ; c < count ; c++ )
{
str = press.SerializeAsString() ;
press2.ParseFromString( str );
}
len = str.length() ;
printf( "[%d]\n" , len );
dump( (char*)str.c_str() , len );
printf( "[%d]\n" , press2.n4() );
printf( "[%lld]\n" , press2.n8() );
printf( "[%d]\n" , press2.un4() );
printf( "[%lld]\n" , press2.un8() );
printf( "[%f]\n" , press2.f4() );
printf( "[%lf]\n" , press2.f8() );
printf( "[%s]\n" , press2.str32().c_str() );
printf( "[%s]\n" , press2.str1024().c_str() );
return 0;
}
...
make
g++ -I. -c test_protobuf_press.cc
g++ -o test_protobuf_press test_protobuf_press.o PressProtobuf.pb.cc -L/usr/local/lib -lprotobuf -lpthread
[/code]
压测输出:
DirectStruct
[code]
time ./test_serialize_compress_press 10000000
AllTypes2.n4[-287454020]
AllTypes2.n8[-1234605616436508552]
AllTypes2.u4[287454020]
AllTypes2.u8[1234605616436508552]
AllTypes2.f4[100.000000]
AllTypes2.f8[10000.000000]
AllTypes2.str32[calvin]
AllTypes2.str1024[XXXXXXXXXXXXXXXX]
Press begin
Press end
data compress size[66] - compact size[1092]
Elapse 1 seconds
0x0000000000 04 11 22 33 44 08 11 22 33 44 55 66 77 88 04 11 .."3D.."3DUfw...
0x0000000001 22 33 44 08 11 22 33 44 55 66 77 88 00 00 c8 42 "3D.."3DUfw....B
0x0000000002 00 00 00 00 00 88 c3 40 01 06 63 61 6c 76 69 6e .......@..calvin
0x0000000003 01 10 58 58 58 58 58 58 58 58 58 58 58 58 58 58 ..XXXXXXXXXXXXXX
0x0000000004 58 58 XX
AllTypes2.n4[-287454020]
AllTypes2.n8[-1234605616436508552]
AllTypes2.u4[287454020]
AllTypes2.u8[1234605616436508552]
AllTypes2.f4[100.000000]
AllTypes2.f8[10000.000000]
AllTypes2.str32[calvin]
AllTypes2.str1024[XXXXXXXXXXXXXXXX]
real 0m1.080s
user 0m1.074s
sys 0m0.007s
[/code]
Google Protocol Buffer
[code]
$ time ./test_protobuf_press 10000000
[-287454020]
[-1234605616436508552]
[287454020]
[1234605616436508552]
[100.000000]
[10000.000000]
[calvin]
[XXXXXXXXXXXXXXXX]
[72]
0x0000000000 10 87 cd 91 92 02 18 8f de b3 d6 8a d1 99 a2 22 ..............."
0x0000000001 28 c4 e6 88 89 01 30 88 ef 99 ab c5 e8 8c 91 11 (.....0.........
0x0000000002 3d 00 00 c8 42 41 00 00 00 00 00 88 c3 40 4a 06 =...BA.......@J.
0x0000000003 63 61 6c 76 69 6e 52 10 58 58 58 58 58 58 58 58 calvinR.XXXXXXXX
0x0000000004 58 58 58 58 58 58 58 58 XXXXXXXX
[-287454020]
[-1234605616436508552]
[287454020]
[1234605616436508552]
[100.000000]
[10000.000000]
[calvin]
[XXXXXXXXXXXXXXXX]
real 0m4.248s
user 0m4.235s
sys 0m0.011s
[/code]
压测结论:
* DirectStruct序列化(带压缩)后的报文大小66字节,而Google Protocol Buffer为72字节,DirectStruct在序列化和压缩报文大小上险胜。
* DirectStruct反复序列化/反序列化(带压缩)1000万次总耗时1.080s,而Google Protocol Buffer总耗时4.248s,DirectStruct在序列化性能上完胜。
* DirectStruct编译客户应用代码时不需要额外的头文件和库文件,只需要工具dsc生成的IDL_AllTypes2.dsc.c、IDL_AllTypes2.dsc.h即可,而Google Protocol Buffer不仅需要PressProtobuf.pb.cc、PressProtobuf.pb.h,还需要/usr/local/include/google/protobuf下的一大堆头文件以及/usr/local/lib/libprotobuf.a(9MB),还依赖于-lpthread,编译环境复杂。
是不是越看越心动了?那就赶紧下载来玩玩吧
N.最后
最近我正在开发一个应用平台,利用tcpdaemon做TCP服务器,利用DirectStruct+fasterxml自动生成的代码轻松解包XML到C结构体,再调用DirectStruct自动生成的ESQL代码INSERT到数据库表里,十几行代码搞定,看,自由组合DirectStruct自动生成的代码能给你带来巨大的便捷性。有了DirectStruct,以后谁还会老老实实的写大量XML转换和ESQL代码呢?
欢迎使用DirectStruct,如果你使用中碰到了问题或者有更酷的想法请告诉我,谢谢 ^_^
首页传送门 : [url]http://git.oschina.net/calvinwilliams/DirectStruct[/url]
作者邮箱 : calvinwilliams.c@gmail.com
C结构体工具DirectStruct(综合示例一)
[url]http://my.oschina.net/u/988092/blog/325072[/url]
C结构体工具DirectStruct(综合示例二)
[url]http://my.oschina.net/u/988092/blog/325073[/url]
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。