Skip to content

使用SWIG生成用于Java调用上期技术CTP-API的JNI(C++)源码

Notifications You must be signed in to change notification settings

sun0x00/swig-java-ctp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

427e93d · Dec 19, 2022

History

6 Commits
Dec 26, 2021
Dec 26, 2021
Dec 26, 2021
Dec 26, 2021
Dec 26, 2021
Dec 26, 2021
Dec 26, 2021
Dec 19, 2022
Dec 19, 2022
Dec 26, 2021
Dec 26, 2021
Dec 27, 2021

Repository files navigation

swig-java-ctp

使用SWIG生成用于Java调用上期技术CTP-API的JNI(C++)源码

简介

本仓库提供 redtorch 项目的rt-gateway-ctp模块的具体代码生成方法和跨平台运行方案细节。

使用方法

  • 下载SWIG软件,并将可执行文件swig.exe(Windows)所在目录加入PATH(或修改run_swig.bat使用绝对路径)
  • 分别运行各目录下的批处理文件run_swig.bat获得Java源码和JNI(C++)源码

提示

  • 本仓库中提供的 .i 文件可跨平台使用,并且生成的JNI(C++)源代码同时适用于Linux和Windows平台
  • 本仓库中CTP相关的头文件 .h 分别来上期技术官网提供的各对应版本的SDK压缩包
  • 自动生成的源码已经默认包含了 libiconv 编码转换方案,具体参考 .i 文件
  • 自动生成的JNI(C++)源码不能解决CTP结算单乱码问题。如需解决结算单乱码问题,请参考下文中提供的参考方案
  • SWIG软件具备跨平台特性,本仓库仅提供Window下的批处理文件 .bat,如需在Linux环境下使用SWIG自动生成源码,请参考 .bat 文件中的生成命令
  • 实际编译时,Windows环境下使用的 iconv 头文件和链接库来自开源项目 libiconv-win-build
  • 实际编译时,Linux环境下使用的 iconv 头文件和链接库请直接使用libiconv官方压编译
  • 实际编译时,需要jni.h和jni_md.h两个头文件,这两个头文件来自Java Development Kit,请在实际使用的JDK中寻找,一般情况下这两个文件也具备跨平台特性

编译

请分别参考以下两个仓库进一步了解编译相关内容

结算单乱码的解决方案

结算单乱码的主要原因是CTP对结算单的完整文本按固定长度的byte数组分段断传输,由于单个unicode字符可能多个byte的情况,因此如果JNI在传输过程中使用iconv转码会丢失数据。

已知的解决方案是修改自动生成后的C++和Java源码(必须同时修复,否则会因JNI类型不匹配而导致崩溃),对结算单相关的数据不使用iconv进行转码,在Java中接收全部的byte数组后拼接为一个完整的byte数组,然后再使用new String构建字符串并使用GB18030(兼容GBK和GB2312)重新编码,此问题便可解决。

下文中提供的方法用于透传结算单分段byte数组数据,不使用iconv转码。

在生成的JNI(C++)源码中搜索 CThostFtdcSettlementInfoField_1Content_1get 将返回类型改为jbyteArray 将函数内容替换为

jbyteArray jresult = 0 ;
CThostFtdcSettlementInfoField *arg1 = (CThostFtdcSettlementInfoField *) 0 ;
char *result = 0 ;

(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CThostFtdcSettlementInfoField **)&jarg1;
result = (char *) ((arg1)->Content);
{
	if (result) {
		jresult = jenv->NewByteArray( strlen(result));
		jenv->SetByteArrayRegion(jresult, 0, strlen(result), (jbyte*)result);
	}
}
return jresult;

最终结果例如:

SWIGEXPORT jbyteArray JNICALL Java_xyz_redtorch_gateway_ctp_x64v6v3v15v_api_jctpv6v3v15x64apiJNI_CThostFtdcSettlementInfoField_1Content_1get(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
	jbyteArray jresult = 0;
	CThostFtdcSettlementInfoField *arg1 = (CThostFtdcSettlementInfoField *)0;
	char *result = 0;

	(void)jenv;
	(void)jcls;
	(void)jarg1_;
	arg1 = *(CThostFtdcSettlementInfoField **)&jarg1;
	result = (char *)((arg1)->Content);
	{
		if (result) {
			jresult = jenv->NewByteArray(strlen(result));
			jenv->SetByteArrayRegion(jresult, 0, strlen(result), (jbyte*)result);
		}

	}
	return jresult;
}

** 请不要直接复制上段函数代码,注意函数名一致性 **

手动将CThostFtdcSettlementInfoField.java文件中的函数 getContent()方法的返回类型改为byte[],将其调用的其他类的方法的返回类型也改为byte[]直到无错为止。

在java中,在没有返回last标记之前,存储所有byte[],返回标记之后拼接为一个大byte[] 使用new String(contentBytes,"GB18030"),便可得到完全正确的结算单。

About

使用SWIG生成用于Java调用上期技术CTP-API的JNI(C++)源码

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages