传统DLL接口规范

来自tradeStar帮助系统
跳转到: 导航, 搜索

目录

DLL接口说明

  1. 扩展函数可用于实现系统公式函数不能实现的特殊算法
  2. 扩展函数用windows 32位动态链接库实现,建议使用Microsoft Visual C++编程.
  3. 调用时在公式编辑器中书写"动态库名称@函数名称"(参数表)即可,例如下面函数"FOXFUNC@MYMACLOSE"(5)
  4. 动态链接库名称和函数名称可以自己定义
  5. 使用时必须将动态库文件放置在软件安装目录下的FmlDLL子目录下

DLL函数格式

DLL名称和函数名称可以自行定义,由于原飞狐公式不区分大小写,DLL的函数名最好使用全大写, 避免某些环境下无法加载,新版本的DLL则无此限制。 下面的例子定义了一个 MYMACLOSE 的函数,函数的实现下面具体分析。

extern "C" __declspec(dllexport) int WINAPI MYMACLOSE(CALCINFO* pData)

DLL函数返回值

首先注意上述函数的返回值是int,这个返回值表示在pData的m_pResultBuf里面有效位置的起始位, m_pResultBuf是DLL返回的数值序列的存放位置,0表示从第1位起有效,2表示从第3位起有效, 返回-1表示全部无效,公式将没有输出。m_pResultBuf和CALCINFO的类型下面讲述

DLL的参数类型

DLL的参数是一个结构体CALCINFO的指针,下面是定义

////////////////////////////////////////////////////
//调用接口信息数据结构
////////////////////////////////////////////////////
typedef struct tagCALCINFO
{
	//结构大小
	DWORD m_dwSize;
	//调用软件版本(V3.00 : 0x300)
	DWORD m_dwVersion;
	//调用软件序列号
	DWORD m_dwSerial;
	//软件用户名
	//char* m_strUserName;
	//股票代码
	char* m_strStkLabel;
	//大盘
	BOOL m_bIndex;
	//数据数量(pData,pDataEx,pResultBuf数据数量)
	int m_nNumData;
	//常规数据,注意:当m_nNumData==0时可能为 NULL
	STKDATA* m_pData;
	//扩展数据,分笔成交买卖盘,注意:可能为 NULL
	STKDATAEx* m_pDataEx;
	//参数1有效位置
	int m_nParam1Start;
	//调用参数1
	float*	 m_pfParam1;
	//调用参数2
	float*	 m_pfParam2;
	//调用参数3
	float*	 m_pfParam3;
	//调用参数4
	float*	 m_pfParam4;				
	//结果缓冲区
	float* m_pResultBuf;
	//数据类型
	int m_dataType;
	//财务数据
	float* m_pfFinData;	
	//以上与分析家兼容,所以沿用其结构和名称

	//以下为 FoxTrader 扩展
	// function type
	DWORD m_nFncType;
	// 调用参数数量
	int m_nNumParam;
	// 调用参数数组
	CALCPARAM* m_pCalcParam;
	//扩展结果缓冲区
	float* m_pResultBufExt[8];
	//扩展结果有效位置
	int m_nResultStart[8];
	// 用户数据(102400字节)
	void* m_pUserData;

	//内部函数计算用
	//参数2有效位置
	int m_nParam2Start; 
	//参数3有效位置
	int m_nParam3Start;
	//参数4有效位置
	int m_nParam4Start;			
	//股票名称
	char* m_strStkName;			
	//除权数据
	SPLITDATA* m_pSplitData;			
	//除权次数
	int m_nNumSplitData;		
	//计算当前下标数据
	int m_iCurIndex;			

	void* m_pReserved1;
	void* m_pReserved2;
	void* m_pReserved3;
	void* m_pReserved4;

} CALCINFO;

注意里面的float* m_pResultBuf;就是函数返回数值序列的存放位置,序列的类型是float, 长度是int m_nNumData;

DLL参数传递

传入DLL的参数是CALCINFO结构体里面的m_pfParam1,m_pfParam2,m_pfParam3,m_pfParam4; 最多可传4个序列。当m_pfParam1为NULL时,表示无参数;当m_pfParam1不为空而m_pfParam2为空表示有1个参数; 当m_pfParam1和m_pfParam2不为空但m_pfParam3为空则表示有两个参数,以此类推。 序列的有效起始位是m_nParam1Start,m_nParam2Start,m_nParam3Start,m_nParam4Start, 起始位小于0表示是单值(用 *m_pfParam1 来获取)。起始位大于等于0时,有效数据为: m_pfParam1[m_nParam1Start],m_pfParam1[m_nParam1Start+1],m_pfParam1[m_nParam1Start+2]...m_pfParam1[m_nNumData-1] 第2,3,4条序列也是同样的结构。

基本数据结构

公式调用DLL时会把当前图形上的信息传入DLL,这些信息包括开高低收量额等, 定义在STKDATA* m_pData这个指针里,长度是m_nNumData, STKDATA结构体的定义如下:

////////////////////////////////////////////////////
//基本数据
////////////////////////////////////////////////////
typedef struct tagSTKDATA	
{
	TimeType m_time;		//时间,UCT
	float	m_fOpen;		//开盘
	float	m_fHigh;		//最高
	float	m_fLow;			//最低
	float	m_fClose;		//收盘
	float	m_fVolume;		//成交量(手)
	float	m_fAmount;		//成交额(元)/持仓(未平仓合约,仅期货有效)
	WORD	m_wAdvance;		//上涨家数(仅大盘有效)
	WORD	m_wDecline;		//下跌家数(仅大盘有效)
} STKDATA;

兼容时间格式

注意上述结构的m_time是TimeType类型,老版本的格式是time_t,由于新版本的time_t是64位的,老飞狐是32位, 所有原来time_t的字段,现在都用TimeType来表示。 使用vc6编译dll的,如果需要用到时间的,时间字段是vc6的time_t类型即可 使用vc2008以上版本的,time_t就是__int64,为了兼容老版本的DLL, 需要使用额外定义下面的TimeType类型(实际上就是int,32位的)

#define TimeType int

扩展数据格式

////////////////////////////////////////////////////
//扩展数据,用于描述分笔成交数据的买卖盘
////////////////////////////////////////////////////
typedef union tagSTKDATAEx
{
	struct
	{
		float m_fBuyPrice[3];		//买1--买3价
		float m_fBuyVol[3];			//买1--买3量
		float m_fSellPrice[3];		//卖1--卖3价	
		float m_fSellVol[3];		//卖1--卖3量
		DWORD m_dwToken;			//成交方向
	};
	float m_fDataEx[13];
} STKDATAEx;

除权数据

////////////////////////////////////////////////////
//除权数据
////////////////////////////////////////////////////
typedef struct tagSPLITDATA	
{
	TimeType	m_time;			//时间,UCT
	float		m_fHg;			//红股
	float		m_fPg;			//配股
	float		m_fPgj;			//配股价
	float		m_fHl;			//红利
} SPLITDATA;

扩展调用参数

////////////////////////////////////////////////////
//调用参数项结构
////////////////////////////////////////////////////
typedef struct tagCALCPARAM
{
	union 
	{
		const float m_fParam; //数值参数
		const float* m_pfParam; //序列参数,指向一个浮点型数组	
		const char* m_szParam; //字符串参数
	};
	//序列参数有效起始位置
	const int	m_nParamStart;
}CALCPARAM;

公式调用例子

公式里使用双引号来调用DLL, 例如下面的例子是调用MyDll.dll里面的MYMACLOSE函数,参数是5, 返回值输出成指标线k1。 下一节有建立DLL工程及调用公式的详细例子。

k1:"MyDll@MYMACLOSE"(5);

开发DLL的详细例子

这里例子是使用VS2012制作的,VS2010,VS2008,VC6也类似。

1. 首先创建Win32的工程项目,项目名称是MyDll

Fml dll create project.png

2. 项目设置成DLL

Fml dll project settings.png

3. 把TimeType, STKDATA, STKDATAEx,等等上述数据结构拷贝到MyDll.cpp

Fml dll edit src.png

4. 添加用户函数MYMACLOSE, 计算 N 日均线

//计算收盘价的均价,一个常数参数,表示计算周期
//调用方法:
//	"FOXFUNC@MYMACLOSE"(5)
extern "C" __declspec(dllexport) int WINAPI MYMACLOSE(CALCINFO* pData)
{

	if ( pData->m_pfParam1 &&				//参数1有效
		 pData->m_nParam1Start<0 &&			//参数1为常数
		 pData->m_pfParam2==NULL )			//仅有一个参数
	{
		float fParam = *pData->m_pfParam1;
		int nPeriod = (int)fParam;			//参数1
		if(nPeriod>0)
		{
			float fTotal;
			int i, j;
			for ( i = nPeriod-1; i < pData->m_nNumData; i++ )//计算nPeriod周期的均线,数据从nPeriod-1开始有效
			{
				fTotal = 0.0f;
				for ( j = 0; j < nPeriod; j++ )				//累加
					fTotal += pData->m_pData[i-j].m_fClose;
				pData->m_pResultBuf[i] = fTotal/nPeriod;	//平均
			}
			return nPeriod-1;
		}
	}
	return -1;
}

5. 设置项目的输出路径为软件安装目录下的 FmlDll 下,输出名称为 MyDll.dll。 这一步可以省略,编译后手动拷贝dll到软件的FmlDll目录也可以

Fml dll linker output.png

6. 编译后,直接运行软件,或者在Debugging调试Command处添加软件的启动路径

7. 创建公式 测试DLL,并编译

Fml dll create fml.png

8. 拖放到图上运行

Fml dll run dll.png

示例DLL工程文件下载

文件:MyDll.zip

返回DLL扩展

个人工具
名字空间

变换
操作
导航
工具箱