美文网首页
金字塔关于DLL调用的问题.md

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

作者: Silent_people | 来源:发表于2020-03-13 20:55 被阅读0次

    [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<vector>
      #include <iostream>
      #include<fstream>
      #include<time.h>
      #include "StockFunc.h"
      
      #define MyClassTestDeBug
      
      using namespace std;
      
      //测试在DLL中运用类对象
      class MyClassTest
      {
      public:
          MyClassTest(CALCINFO* pData);
          ~MyClassTest();
          void MyCalMa(int _nPeriod); //计算均线
          vector<float> 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<float>& 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<float>& 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

          本文链接:https://www.haomeiwen.com/subject/ocpyshtx.html