[TOC]
1.编译环境及版本信息
- 金字塔版本
金字塔决策交易系统(x86)2020(v5.21) - IDE
Visual Studio Community 2019 版本 16.4.6
2. 问题描述
- 在金字塔软件中,在公式里序列模式下调用DLL扩展函数时,使用了类,在调用该函数时在全局区定义了一个全局变量并置为空,然后在调用的函数处,通过new的方式创建一个对象,并把全局指针变量指向该对象;通过打印文件方式查看到当在金字塔软件里公式调用该DLL函数时,当改变品种或者周期时并没有调用析构函数,但是却新调用了构造函数创建了新的类对象,这里是金字塔通过DLL管理这一块堆上的内存还是用户自己要在DLL里自己进行管理,是否会存在内存泄露的问题?
- 在上诉函数之后,再调用其他函数,该全局指针并未指向上一个函数所产生的对象?要在其他函数里使用其中一个函数中创建的类对象,要进行怎样的定义才行?
3. 想要实现的目的
想要实现的目的:比如在 MYMACLOSE_TEST1
中创建了一个类,怎样才能在 MYMACLOSE_TEST2
函数中调用上面 MYMACLOSE_TEST1
中创建的对象,这样就可以调用返回对象的多个属性而不用多次创建,因为用 pData->m_pResultBuf[]
返回值时只能返回一组计算值,当想要返回其他组的计算值是要另外返回 pData->m_pResultBuf[]
才能再公式里获得!
4. 打印的记录信息
5. 测试代码
-
金字塔公式
MYMACLOSE_TEST1:"CTestDemo@MYMACLOSE_TEST1"(5); MYMACLOSE_TEST2:"CTestDemo@MYMACLOSE_TEST2"(5);
目的就是想用
MYMACLOSE_TEST2
调用MYMACLOSE_TEST1
中创建的对象,这样就不用重复再计算了,因为如果对象中有多个属性需要返回时,好像只能通过多次函数调用返回! -
DLL中的代码:
- 测试类的代码:
#pragma once #include
#include #include #include #include "StockFunc.h" #define MyClassTestDeBug using namespace std; //测试在DLL中运用类对象 class MyClassTest { public: MyClassTest(CALCINFO* pData); ~MyClassTest(); void MyCalMa(int _nPeriod); //计算均线 vector c_MaData; //结果值 private: CALCINFO* c_pData_test; }; MyClassTest::MyClassTest(CALCINFO* pData) { c_pData_test = pData; #ifdef MyClassTestDeBug ofstream outfile; //outfile.imbue(locale(locale(), "", LC_CTYPE)); // ① outfile.open("./Document/ctestdomedebug.txt", ios::app); //"D:/Program Files (x86)/Weisoft Stock(x86)/Document/clcdebug.txt" if (outfile.is_open()) { outfile.imbue(locale("", locale::all ^ locale::numeric)); time_t time_seconds = time(NULL); struct tm now_time; localtime_s(&now_time, &time_seconds); char str[26]; strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", &now_time); outfile << __FUNCTION__ << " ; c_pData_test->m_nNumData: " << c_pData_test->m_nNumData << " ; c_MaData.size: " << c_MaData.size() << " "; outfile << " name: " << c_pData_test->m_strStkName << "; label:" << (string)c_pData_test->m_strStkLabel << " ; run_time: " << str << endl; outfile << "--------------------------------------------------------------" << endl; } outfile.close(); #endif // MyClassTestDeBug 输出类属性StockFunc.h中的结构、均线计算的结果值 } MyClassTest::~MyClassTest() { #ifdef MyClassTestDeBug ofstream outfile; outfile.open("./Document/ctestdomedebug.txt", ios::app); //"D:/Program Files (x86)/Weisoft Stock(x86)/Document/clcdebug.txt" if (outfile.is_open()) { time_t time_seconds = time(NULL); struct tm now_time; localtime_s(&now_time, &time_seconds); char str[26]; strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", &now_time); outfile << __FUNCTION__ << " ; c_MaData.size: " << c_MaData.size() << " " << str << endl; outfile << "--------------------------------------------------------------" << endl; } outfile.close(); #endif // MyClassTestDeBug } inline void MyClassTest::MyCalMa(int _nPeriod) { if (_nPeriod > 0) { float fTotal; float fCal; int i(0), j(0); for (i = 0; i < c_pData_test->m_nNumData; i++)//计算_nPeriod周期的均线,数据从_nPeriod-1开始有效 { fTotal = 0.0f; fCal = 0.0f; if (i >= _nPeriod - 1) { for (j = 0; j < _nPeriod; j++) //累加 { fTotal += c_pData_test->m_pData[i - j].m_fClose; } } fCal = fTotal / _nPeriod; //平均 c_MaData.push_back(fCal); } } #ifdef MyClassTestDeBug ofstream outfile; outfile.open("./Document/ctestdomedebug.txt", ios::app); //"D:/Program Files (x86)/Weisoft Stock(x86)/Document/clcdebug.txt" if (outfile.is_open()) { time_t time_seconds = time(NULL); struct tm now_time; localtime_s(&now_time, &time_seconds); char str[26]; strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", &now_time); outfile << __FUNCTION__ << " ; c_pData_test->m_nNumData: " << c_pData_test->m_nNumData << " ; c_MaData.size: " << c_MaData.size() << " " << str << endl; outfile << "--------------------------------------------------------------" << endl; } outfile.close(); #endif // MyClassTestDeBug } - 返回调用部分代码:
// StockFunc.cpp : Defines the entry point for the DLL application.
//
#include "pch.h" //#include "stdafx.h"
#include "StockFunc.h"
#include "CTestDemo.h"
#include "stdio.h"
#include "vector"
#define Test_Interface_DeBug
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
//DLL公式的运行模式,系统系统调用该DLL时,告知公式系统该DLL公式运行在何种模式下
//返回值: 0本DLL运行序列模式 1本DLL运行逐周期模式
__declspec(dllexport) int WINAPI RUNMODE()
{
//本DLL运行序列模式,如果运行逐K线模式将此函数返回1,此时每执行一个K线都是调用本接口一次。
// return 1;
return 0;
}
//测试对象函数部分
MyClassTest* instance = nullptr; //定义一个类指针的全局变量,目的是为了下面的MYMACLOSE_TEST2也能够通过这个指针获得类属性
__declspec(dllexport) int WINAPI MYMACLOSE_TEST1(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
instance = new MyClassTest(pData); //类的实例化
instance->MyCalMa(nPeriod); //计算均线值
const std::vector& maData = instance->c_MaData; //获得类属性(均线值)
for (int i = nPeriod - 1; i < (int)maData.size(); i++)//计算nPeriod周期的均线,数据从nPeriod-1开始有效
{
pData->m_pResultBuf[i] = maData[i]; //平均
}
#ifdef Test_Interface_DeBug
ofstream outfile;
outfile.open("./Document/ctestdomedebug.txt", ios::app); //"D:/Program Files (x86)/Weisoft Stock(x86)/Document/clcdebug.txt"
if (outfile.is_open())
{
time_t time_seconds = time(NULL); struct tm now_time; localtime_s(&now_time, &time_seconds);
char str[26]; strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", &now_time);
outfile << __FUNCTION__ << " ; maData.size: " << maData.size() << " " << str << endl;
outfile << "instance指向的地址:" << instance <<" ; 获得的类属性(返回的均线值)的地址:"<< &maData<< endl;
outfile << "--------------------------------------------------------------" << endl;
}
outfile.close();
#endif // Test_Interface_DeBug
return nPeriod - 1;
}
return -1;
}
//该函数测试上面全局变量instance是否可用?
__declspec(dllexport) int WINAPI MYMACLOSE_TEST2(CALCINFO* pData)
{
if (pData->m_pfParam1 && //参数1有效
pData->m_nParam1Start < 0 && //参数1为常数
pData->m_pfParam2 == NULL) //仅有一个参数
{
#ifdef Test_Interface_DeBug
ofstream outfile;
outfile.open("./Document/ctestdomedebug.txt", ios::app); //"D:/Program Files (x86)/Weisoft Stock(x86)/Document/clcdebug.txt"
if (outfile.is_open())
{
time_t time_seconds = time(NULL); struct tm now_time; localtime_s(&now_time, &time_seconds);
char str[26]; strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", &now_time);
outfile << __FUNCTION__ << " ; pData->m_nNumData: " << pData->m_nNumData << " " << str << endl;
outfile << "instance指向的地址:" << instance << endl;
outfile << "--------------------------------------------------------------" << endl;
}
outfile.close();
#endif // Test_Interface_DeBug
float fParam = *pData->m_pfParam1;
int nPeriod = (int)fParam; //参数1
//instance = new MyClassTest(pData); //类的实例化
//instance->MyCalMa(nPeriod); //计算均线值
if (instance == nullptr)
{
#ifdef Test_Interface_DeBug
ofstream outfile1;
outfile1.open("./Document/ctestdomedebug.txt", ios::app); //"D:/Program Files (x86)/Weisoft Stock(x86)/Document/clcdebug.txt"
if (outfile1.is_open())
{
time_t time_seconds = time(NULL); struct tm now_time; localtime_s(&now_time, &time_seconds);
char str[26]; strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", &now_time);
outfile1 << __FUNCTION__ << " 类对象指针指向的均线属性是否为空:" << instance->c_MaData.empty() << " " << str << endl;
outfile1 << "--------------------------------------------------------------" << endl;
}
outfile1.close();
#endif // Test_Interface_DeBug
return -1;
}
const std::vector& maData = instance->c_MaData; //获得类属性(均线值)
for (int i = nPeriod - 1; i < (int)maData.size(); i++)//计算nPeriod周期的均线,数据从nPeriod-1开始有效
{
pData->m_pResultBuf[i] = maData[i] * 1.01f; //平均
}
#ifdef Test_Interface_DeBug
ofstream outfile2;
outfile2.open("./Document/ctestdomedebug.txt", ios::app); //"D:/Program Files (x86)/Weisoft Stock(x86)/Document/clcdebug.txt"
if (outfile2.is_open())
{
time_t time_seconds = time(NULL); struct tm now_time; localtime_s(&now_time, &time_seconds);
char str[26]; strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", &now_time);
outfile2 << __FUNCTION__ << " ; maData.size: " << maData.size() << " " << str << endl;
outfile2 << "--------------------------------------------------------------" << endl;
}
outfile2.close();
#endif // Test_Interface_DeBug
return nPeriod - 1;
}
return -1;
}