开发Beckhoff ADS DLL测试程序时遇E0337/C2065等编译错误求助
问题:调用Beckhoff ADS DLL的测试程序编译报错
已完成读取Beckhoff PLC数据的DLL开发,DLL编译无报错,但测试程序编译时出现以下错误:
>E0337 linkage specification is incompatible with previous "AdsAmsPortEnabled" (declared at line 143) famosAdsTestEnvironment C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h Error (active) E0067 expected a '}' famosAdsTestEnvironment C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h Error C2065 'NULL': undeclared identifier famosAdsTestEnvironment C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h Error C2065 'BOOL': undeclared identifier famosAdsTestEnvironment C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h Error C2065 'pbEnabled': undeclared identifier famosAdsTestEnvironment C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h Error C2061 syntax error: identifier 'BOOL' famosAdsTestEnvironment C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h
错误均指向Beckhoff提供的只读ADS头文件,推测是头文件引用问题,相关代码如下:
DLL头文件(famosAdsLibrary.h)
#pragma once #include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h" #include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h" #ifdef FAMOSADSLIBRARY_EXPORTS #define FAMOSADSLIBRARY_API __declspec(dllexport) #else #define FAMOSADSLIBRARY_API __declspec(dllimport) #endif class FAMOSADSLIBRARY_API adsCommunication { private: long nErr, nPort = 0; AmsAddr Addr; PAmsAddr pAddr = &Addr; int adress; int datatyp; public: adsCommunication(int datatyp = 0x4, int adress = 0x0) { this->datatyp = datatyp; this->adress = adress; } void connectADS(); void disconnectADS(); float readADS(); void writeADS(int data); };
DLL主程序(famosAdsLibrary.cpp)
#include "pch.h" #include "famosAdsLibrary.h" #include <iostream> #include "framework.h" #include <conio.h> #include <windows.h> using namespace std; BOOL APIENTRY DllMain( HMODULE 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; } void adsCommunication::connectADS() { // Open communication port on the ADS router nPort = AdsPortOpen(); nErr = AdsGetLocalAddress(pAddr); if (nErr) cerr << "Error: AdsGetLocalAddress: " << nErr << '\n'; pAddr->port = 851; } float adsCommunication::readADS() { INT data = 0; nErr = AdsSyncReadReq(pAddr, 0x4020, adress, datatyp, &data); if (nErr) cerr << "Error: AdsSyncReadReq: " << nErr << '\n'; cout << data << endl; return data; } void adsCommunication::writeADS(int data) { nErr = AdsSyncWriteReq(pAddr, 0x4020, adress, datatyp, &data); if (nErr) cerr << "Error: AdsSyncWriteReq: " << nErr << '\n'; } void adsCommunication::disconnectADS() { nErr = AdsPortClose(); if (nErr) cerr << "Error: AdsPortClose: " << nErr << '\n'; }
测试程序头文件(Main.h)
#pragma once #include <famosAdsLibrary.h> #include <Windows.h>
测试程序主程序(Main.cpp)
#include "Main.h" int main() { int value = 0; adsCommunication data(0x4, 0x0); data.connectADS(); while (1) { value = data.readADS(); if (value >= 800) { value = 0; data.writeADS(wert); } } data.disconnectADS(); system("PAUSE"); return 0; }
出错的Beckhoff头文件片段(TcAdsAPI.h)
#ifndef __ADSAPI_H__ #define __ADSAPI_H__ #define ADSAPIERR_NOERROR 0x0000 #ifdef __cplusplus extern "C" { #endif //other dllexports without error __declspec( dllexport ) long __stdcall AdsAmsPortEnabled(BOOL *pbEnabled); // more dllexports without error __declspec( dllexport ) long __stdcall AdsAmsPortEnabledEx(long nPort, BOOL *pbEnabled);
解决方案
1. 修复头文件引用顺序,确保系统头文件优先
Beckhoff的ADS头文件依赖Windows.h定义的BOOL、NULL等类型,必须在引用TcAdsDef.h和TcAdsAPI.h前包含Windows.h:
修改DLL头文件(famosAdsLibrary.h):
#pragma once #include <windows.h> // 移到最前面 #include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h" #include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h" #ifdef FAMOSADSLIBRARY_EXPORTS #define FAMOSADSLIBRARY_API __declspec(dllexport) #else #define FAMOSADSLIBRARY_API __declspec(dllimport) #endif // ... 其余代码不变
修改测试程序头文件(Main.h):
#pragma once #include <Windows.h> // 移到famosAdsLibrary.h之前 #include <famosAdsLibrary.h>
2. 确认extern "C"块的完整性
报错中的expected a '}'说明TcAdsAPI.h里的extern "C"块可能没有正确闭合。检查该头文件末尾是否有:
#ifdef __cplusplus } #endif
如果缺失,需重新获取官方完整的ADS头文件。
3. 修复测试程序中的变量错误
测试主程序里的data.writeADS(wert);中wert未定义,应改为value:
if (value >= 800) { value = 0; data.writeADS(value); // 替换wert为value }
4. 统一编译环境设置
确保DLL和测试程序使用相同的编译选项:
- 均为32位或64位编译(需匹配ADS DLL的对应版本)
- 使用相同的运行时库(如MT/MD)
内容的提问来源于stack exchange,提问作者excellent
相关产品推荐
相关产品推荐

