首页 > 解决方案 > WinAPI/MFC 用户自定义函数

问题描述

我有一个简单的 C++ 控制台应用程序,用于驱动色度计。__cdecl与设备接口的函数以带有函数的 MSVC DLL 的形式提供。

我也得到了相应的.h.lib文件。所有处理都依赖于需要在启动时实例化的事件处理程序。它从 DLL 函数中调用,以在数据准备好检索时发出警报。该设备连接到 USB 端口并在设备管理器 (COM0) 中显示为(虚拟?)COM 端口。

我需要将这个简单的应用程序“移植”到 GUI 环境来维持我的项目。我尝试了 QT Creator 5.15.2(带有 MinGW 开源选项)和 Embarcadero C++Builder,但是从这些环境访问 DLL 函数是不可能的。我尝试了 wxWidget,但它对我来说“不起作用”——由于某种原因(找不到“Main/Invoke”?),我无法让 Sample 执行。

所以我把注意力转向了 MFC 和 WinAPI。创建一个 C++ MFC 应用程序是“直截了当”的,直到我必须弄清楚我的设备“如何连接”这个系统。我尝试创建一个自定义类,myDevice重新组合我的所有自定义函数,例如“连接”、“校准”和“测量”。

main.h中,我声明了这个类:

class myDevice{
private:
   //bool CalibratedStatus;
public:
   bool Connect();
   bool Calibrate();
   bool Measure();
   myDevice();
   ~myDevice();
};

然后在 中Main.cpp,我有成员函数定义:

MainApp::MainApp()
{
    // TODO: add construction code here,
    DEVICE_ERROR_TYPES deviceError = DEVICE_RegisterDeviceEventHandler(EventNotice);

    // Place all significant initialization in InitInstance
}

myDevice::MyDEVICE() { }
myDevice::~MyDEVICE() { }

bool myDevice::Connect() {

    string StatusDEVICE;
    uint8 StateTableRB, portInfoName, portInfoSerialNo;
    string DevicePortList;
    uint32 portCount = 0;
    DEVICE_PortInfo portInfo[16];
    uint8 StateTable[2][4] = { "Eth", "USB" };

    // "01 Looking for the instrument...
    DEVICE_GetDevicePortList(0, &portCount, 0);

    if (portCount > 16) {
        portCount = 16;
    }
    else if (portCount < 1) {
        // printf("device not found\n");
       return false;
    }

    DEVICE_GetDevicePortList(portInfo, &portCount, portCount);  // display device list

    deviceError = DEVICE_Connect(&portInfo[0], 10);

    if (DEVICE_SUCCESSFUL(deviceError)) {
        StatusDEVICE = "Device Connect Complete!";
        // printf("Device Connect Complete!\n");
        return true;
    }
}

bool myDevice::Calibrate() { }

bool myDevice::Measure() {

    if (CalibratedStatus == true) {

        // Set measure condition
        DEVICE_MeasureCondition measureCondition = { measureType, 0 };
        deviceError = DEVICE_SetMeasureCondition(&measureCondition);
        // start measurement
        deviceError = DEVICE_StartMeasurement();

        if (device_SUCCESSFUL(deviceError)) {
           while (!isMeasureWait) {
               if (isDisConnect) break; 
               // waiting for measurement complete
                  this_thread::sleep_for(chrono::milliseconds(1000));
           }
           ExportMeasureData(measureType);
           isMeasureWait = true;
           return true;
        }
        else return false;
    }
}

然后我需要使用这些标志:

bool isMeasureCompleted = false;
bool isCcalibrationCompleted = false;
bool isCcalibrationFailed = false;
bool isMeasureWait = false;

我把它放在这MainApp::MainApp()条线的上方(Globals?)。

我承认我没有任何 MFC 或 WinAPI 编码经验,但我有一种预感,这与在源文件中间的某处声明事件处理程序并随后是一堆检索数据的松散函数完全不同。

不知何故,我不清楚在哪里可以放置像这些“战略性”这样的“用户定义的函数”?并调用?如果我创建一个按钮,比如说,在按钮处理程序中“连接”到设备,它是很容易放置连接到设备的代码并从那里执行。但是“返回”呢?因为返回不是“直接”(可能是“异步”?);返回总是走事件的路线处理程序并降落在事件通知中,我有一个 Switch 语句,它将任务重定向到与“收到的事件”相对应的函数。我无法更改该行为。

我正在阅读有关串行通信应用程序的信息,据我所知,这些应用程序使用 MFC 中的“串行事件”来触发对函数的调用?但这对我来说真的很“新”。我不确定这是否是一个好方法?正如您在上面的代码中看到的那样,有一个“线程睡眠”在“设备忙时”执行?设备完成后,它会自行调用事件通知处理程序及其响应:

void EventNotice(DEVICE_EventCode outEventCode, uint32 outRAWDataCount, DEVICE_ERROR_TYPES outError)
{
       switch (outEventCode) {
         case Event_Standby:        // 0
            // cout << "Standby..." << endl;
             break;
         case Event_MeasureWait:        // 1
            if (isMeasureCompleted) {
               // export measure data
               // printf("\n04 Export Measure Data...");
               ExportMeasureData(measureType);          
               isMeasureWait = true;
         case ...

我需要能够按原样实现此事件处理程序功能吗?否则,我无权访问该设备。

这就是我不确定如何在“消息处理”方法中做到这一点的地方:我不能只是在任何地方“转储”事件处理程序代码并期望设备自己通过魔法找到事件处理程序,对吧? 它不像在简单的程序程序中那样工作,是吗?

我一直在阅读很多关于如何将我愚蠢的控制台应用程序代码转换为 MFC/WinAPI 的文章,但我发现的只是关于如何使用API 本身、如何创建按钮、菜单和资源的参考,但与我的完全不同我试图完成。

==== 2021 年 4 月 14 日更新

@Remy:我将 DLL 函数调用移出我的类,现在从链接器收到另一种错误。以前,错误指的是“public: __thiscall”......,现在,错误指的是“public: __cdecl”。

我今天早上读到 C++ 函数总是以“__thiscall”为前缀?我摆脱了 __thiscall 前缀,但链接器仍然无法找到函数。带有 __cdel 前缀。顺便说一句,我很想C++ Builder 开始这个项目!我尝试使用 IMPLIB 和 COFF2OMF,然后使用 IMPDEF,但未能成功强制 DLL 与 C++ Builder 一起使用,但无济于事。从文档中:C++Builder 不能使用来自其他编译器的 .lib 文件,只能使用它自己的。如果 .lib 文件是 DLL 的导入库,请使用 C++Builder 的命令行 IMPLIB 工具直接从 DLL 创建新的 .lib 文件。这就是我所做的(尽我所能)。最后,我在我的源文件中使用了这条语句将编译器定向到我的新 .lib 版本:#pragma comment(lib, "FDXSDK.lib"

这是我从 IMDEF 获得的 EDF 的前四行:

LIBRARY DEVICE.DLL 导出 DEVICE_CalculateMeasureData @60 ; DEVICE_CalculateMeasureData DEVICE_Calibration @61 ; DEVICE_Calibration

我尝试联系 Embarcadero 支持,但由于我只使用“社区”版本,因此没有支持——忘记论坛。我搜索了我能找到的所有参考资料,并在放弃之前尝试了所有我能做的事情。

归根结底,我仍然从 Embarcadero Linker 获得“未解决的参考”。

=== UPDATE 2 / 2021 04 15 ================= 我查看了 Dumpbin 实用程序以检查 DLL 中的函数名称并得到此输出(仅显示第一行) :

dumpbin DEVICE.dll /EXPORTS Microsoft (R) COFF/PE Dumper 版本 14.28.29913.0 版权所有 (C) Microsoft Corporation。版权所有。

文件 device.dll 的转储

文件类型:DLL

部分包含 DEVICE.dll 的以下导出

00000000 characteristics
FFFFFFFF time date stamp
    0.00 version
       1 ordinal base
      91 number of functions
      91 number of names

ordinal hint RVA      name

     60    0 0003E2F0 DEVICE_Calculate
     61    1 0003DA60 DEVICE_Calibrate
     62    2 0003DE10 DEVICE_Cancel
     63    3 0003D7D0 DEVICE_Connect
     64    4 0003D8E0 DEVICE_Disconnect

标签: c++winapimfc

解决方案


推荐阅读