金字塔关于DLL调用的问题.md

[TOC]

1.编译环境及版本信息

  1. 金字塔版本
    金字塔决策交易系统(x86)2020(v5.21)
  2. IDE
    Visual Studio Community 2019 版本 16.4.6

2. 问题描述

  1. 在金字塔软件中,在公式里序列模式下调用DLL扩展函数时,使用了类,在调用该函数时在全局区定义了一个全局变量并置为空,然后在调用的函数处,通过new的方式创建一个对象,并把全局指针变量指向该对象;通过打印文件方式查看到当在金字塔软件里公式调用该DLL函数时,当改变品种或者周期时并没有调用析构函数,但是却新调用了构造函数创建了新的类对象,这里是金字塔通过DLL管理这一块堆上的内存还是用户自己要在DLL里自己进行管理,是否会存在内存泄露的问题?
  2. 在上诉函数之后,再调用其他函数,该全局指针并未指向上一个函数所产生的对象?要在其他函数里使用其中一个函数中创建的类对象,要进行怎样的定义才行?

3. 想要实现的目的

想要实现的目的:比如在 MYMACLOSE_TEST1 中创建了一个类,怎样才能在 MYMACLOSE_TEST2 函数中调用上面 MYMACLOSE_TEST1 中创建的对象,这样就可以调用返回对象的多个属性而不用多次创建,因为用 pData->m_pResultBuf[] 返回值时只能返回一组计算值,当想要返回其他组的计算值是要另外返回 pData->m_pResultBuf[] 才能再公式里获得!

4. 打印的记录信息

Snipaste_2020-03-13_20-14-17.png
Snipaste_2020-03-13_20-16-27.png

5. 测试代码

  1. 金字塔公式

    MYMACLOSE_TEST1:"CTestDemo@MYMACLOSE_TEST1"(5);
    MYMACLOSE_TEST2:"CTestDemo@MYMACLOSE_TEST2"(5);
    

    目的就是想用 MYMACLOSE_TEST2 调用 MYMACLOSE_TEST1 中创建的对象,这样就不用重复再计算了,因为如果对象中有多个属性需要返回时,好像只能通过多次函数调用返回!

  2. 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;
}

你可能感兴趣的:(金字塔关于DLL调用的问题.md)