[TOC]
1.編譯環(huán)境及版本信息
- 金字塔版本
金字塔決策交易系統(tǒng)(x86)2020(v5.21) - IDE
Visual Studio Community 2019 版本 16.4.6
2. 問(wèn)題描述
- 在金字塔軟件中,在公式里序列模式下調(diào)用DLL擴(kuò)展函數(shù)時(shí),使用了類粗俱,在調(diào)用該函數(shù)時(shí)在全局區(qū)定義了一個(gè)全局變量并置為空寸认,然后在調(diào)用的函數(shù)處偏塞,通過(guò)new的方式創(chuàng)建一個(gè)對(duì)象灸叼,并把全局指針變量指向該對(duì)象;通過(guò)打印文件方式查看到當(dāng)在金字塔軟件里公式調(diào)用該DLL函數(shù)時(shí)捉腥,當(dāng)改變品種或者周期時(shí)并沒有調(diào)用析構(gòu)函數(shù)但狭,但是卻新調(diào)用了構(gòu)造函數(shù)創(chuàng)建了新的類對(duì)象,這里是金字塔通過(guò)DLL管理這一塊堆上的內(nèi)存還是用戶自己要在DLL里自己進(jìn)行管理剥槐,是否會(huì)存在內(nèi)存泄露的問(wèn)題粒竖?
- 在上訴函數(shù)之后,再調(diào)用其他函數(shù)朽砰,該全局指針并未指向上一個(gè)函數(shù)所產(chǎn)生的對(duì)象漆弄?要在其他函數(shù)里使用其中一個(gè)函數(shù)中創(chuàng)建的類對(duì)象撼唾,要進(jìn)行怎樣的定義才行?
3. 想要實(shí)現(xiàn)的目的
想要實(shí)現(xiàn)的目的:比如在 MYMACLOSE_TEST1
中創(chuàng)建了一個(gè)類糙箍,怎樣才能在 MYMACLOSE_TEST2
函數(shù)中調(diào)用上面 MYMACLOSE_TEST1
中創(chuàng)建的對(duì)象猴伶,這樣就可以調(diào)用返回對(duì)象的多個(gè)屬性而不用多次創(chuàng)建他挎,因?yàn)橛?pData->m_pResultBuf[]
返回值時(shí)只能返回一組計(jì)算值,當(dāng)想要返回其他組的計(jì)算值是要另外返回 pData->m_pResultBuf[]
才能再公式里獲得呢撞!
4. 打印的記錄信息
Snipaste_2020-03-13_20-14-17.png
Snipaste_2020-03-13_20-16-27.png
5. 測(cè)試代碼
-
金字塔公式
MYMACLOSE_TEST1:"CTestDemo@MYMACLOSE_TEST1"(5); MYMACLOSE_TEST2:"CTestDemo@MYMACLOSE_TEST2"(5);
目的就是想用
MYMACLOSE_TEST2
調(diào)用MYMACLOSE_TEST1
中創(chuàng)建的對(duì)象,這樣就不用重復(fù)再計(jì)算了绷蹲,因?yàn)槿绻麑?duì)象中有多個(gè)屬性需要返回時(shí)祝钢,好像只能通過(guò)多次函數(shù)調(diào)用返回! -
DLL中的代碼:
- 測(cè)試類的代碼:
#pragma once #include<vector> #include <iostream> #include<fstream> #include<time.h> #include "StockFunc.h" #define MyClassTestDeBug using namespace std; //測(cè)試在DLL中運(yùn)用類對(duì)象 class MyClassTest { public: MyClassTest(CALCINFO* pData); ~MyClassTest(); void MyCalMa(int _nPeriod); //計(jì)算均線 vector<float> c_MaData; //結(jié)果值 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中的結(jié)構(gòu)灾常、均線計(jì)算的結(jié)果值 } 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++)//計(jì)算_nPeriod周期的均線,數(shù)據(jù)從_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 }
- 返回調(diào)用部分代碼:
// 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公式的運(yùn)行模式,系統(tǒng)系統(tǒng)調(diào)用該DLL時(shí)监徘,告知公式系統(tǒng)該DLL公式運(yùn)行在何種模式下
//返回值: 0本DLL運(yùn)行序列模式 1本DLL運(yùn)行逐周期模式
__declspec(dllexport) int WINAPI RUNMODE()
{
//本DLL運(yùn)行序列模式凰盔,如果運(yùn)行逐K線模式將此函數(shù)返回1,此時(shí)每執(zhí)行一個(gè)K線都是調(diào)用本接口一次尿庐。
// return 1;
return 0;
}
//測(cè)試對(duì)象函數(shù)部分
MyClassTest* instance = nullptr; //定義一個(gè)類指針的全局變量抄瑟,目的是為了下面的MYMACLOSE_TEST2也能夠通過(guò)這個(gè)指針獲得類屬性
__declspec(dllexport) int WINAPI MYMACLOSE_TEST1(CALCINFO* pData)
{
if (pData->m_pfParam1 && //參數(shù)1有效
pData->m_nParam1Start < 0 && //參數(shù)1為常數(shù)
pData->m_pfParam2 == NULL) //僅有一個(gè)參數(shù)
{
float fParam = *pData->m_pfParam1;
int nPeriod = (int)fParam; //參數(shù)1
instance = new MyClassTest(pData); //類的實(shí)例化
instance->MyCalMa(nPeriod); //計(jì)算均線值
const std::vector<float>& maData = instance->c_MaData; //獲得類屬性(均線值)
for (int i = nPeriod - 1; i < (int)maData.size(); i++)//計(jì)算nPeriod周期的均線,數(shù)據(jù)從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;
}
//該函數(shù)測(cè)試上面全局變量instance是否可用惹资?
__declspec(dllexport) int WINAPI MYMACLOSE_TEST2(CALCINFO* pData)
{
if (pData->m_pfParam1 && //參數(shù)1有效
pData->m_nParam1Start < 0 && //參數(shù)1為常數(shù)
pData->m_pfParam2 == NULL) //僅有一個(gè)參數(shù)
{
#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; //參數(shù)1
//instance = new MyClassTest(pData); //類的實(shí)例化
//instance->MyCalMa(nPeriod); //計(jì)算均線值
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__ << " 類對(duì)象指針指向的均線屬性是否為空:" << instance->c_MaData.empty() << " " << str << endl;
outfile1 << "--------------------------------------------------------------" << endl;
}
outfile1.close();
#endif // Test_Interface_DeBug
return -1;
}
const std::vector<float>& maData = instance->c_MaData; //獲得類屬性(均線值)
for (int i = nPeriod - 1; i < (int)maData.size(); i++)//計(jì)算nPeriod周期的均線,數(shù)據(jù)從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;
}