尝试在多个文件中使用 Azure-iot-sdk-c 序列化程序模型时出现链接器错误

Linker error when trying to use Azure-iot-sdk-c serializer model in multiple files

我尝试在多个文件中使用带有 azure-iot-sdk-c 的序列化程序模型。只要我只在主文件中使用它,一切都会编译。

但是当我在另一个头文件中声明模型,在相应的c文件和主文件中使用它时,我得到一个链接器错误:

CMakeFiles/simplesample_amqp.dir/otherfile.c.o: In function `FromAGENT_DATA_TYPE_ContosoAnemometer':
otherfile.c:(.text+0x1165): multiple definition of `FromAGENT_DATA_TYPE_ContosoAnemometer'
CMakeFiles/simplesample_amqp.dir/simplesample_amqp.c.o:simplesample_amqp.c:(.text+0x1165): first defined here
collect2: error: ld returned 1 exit status
serializer/samples/simplesample_amqp/CMakeFiles/simplesample_amqp.dir/build.make:160: recipe for target 'serializer/samples/simplesample_amqp/simplesample_amqp' failed
make[2]: *** [serializer/samples/simplesample_amqp/simplesample_amqp] Error 1
CMakeFiles/Makefile2:3947: recipe for target 'serializer/samples/simplesample_amqp/CMakeFiles/simplesample_amqp.dir/all' failed
make[1]: *** [serializer/samples/simplesample_amqp/CMakeFiles/simplesample_amqp.dir/all] Error 2

我通过改编 serializer/samples/simplesample_amqp 示例尝试了此操作:

diff --git a/serializer/samples/simplesample_amqp/CMakeLists.txt b/serializer/samples/simplesample_amqp/CMakeLists.txt
index 4f26060..52d55d7 100644
--- a/serializer/samples/simplesample_amqp/CMakeLists.txt
+++ b/serializer/samples/simplesample_amqp/CMakeLists.txt
@@ -11,6 +11,7 @@ endif()

 set(simplesample_amqp_c_files
 simplesample_amqp.c
+otherfile.c
 )

 if(WIN32)
@@ -21,6 +22,7 @@ endif()

 set(simplesample_amqp_h_files
 simplesample_amqp.h
+otherfile.h
 )

 IF(WIN32)
diff --git a/serializer/samples/simplesample_amqp/simplesample_amqp.c b/serializer/samples/simplesample_amqp/simplesample_amqp.c
index 0a9c9a8..b312c9c 100644
--- a/serializer/samples/simplesample_amqp/simplesample_amqp.c
+++ b/serializer/samples/simplesample_amqp/simplesample_amqp.c
@@ -26,24 +26,11 @@
 #include "certs.h"
 #endif // SET_TRUSTED_CERT_IN_SAMPLES

+#include "otherfile.h"
+
 /*String containing Hostname, Device Id & Device Key in the format:             */
 /*  "HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>"    */
-static const char* connectionString = "[device connection string]";
-
-// Define the Model
-BEGIN_NAMESPACE(WeatherStation);
-
-DECLARE_MODEL(ContosoAnemometer,
-WITH_DATA(ascii_char_ptr, DeviceId),
-WITH_DATA(int, WindSpeed),
-WITH_DATA(float, Temperature),
-WITH_DATA(float, Humidity),
-WITH_ACTION(TurnFanOn),
-WITH_ACTION(TurnFanOff),
-WITH_ACTION(SetAirResistance, int, Position)
-);
-
-END_NAMESPACE(WeatherStation);
+static const char* connectionString = "";

 static char propText[1024];

@@ -199,10 +186,8 @@ void simplesample_amqp_run(void)
                     }
                     else
                     {
-                        myWeather->DeviceId = "myFirstDevice";
-                        myWeather->WindSpeed = avgWindSpeed + (rand() % 4 + 2);
-                        myWeather->Temperature = minTemperature + (rand() % 10);
-                        myWeather->Humidity = minHumidity + (rand() % 20);
+                                               myWeather->DeviceId = "myFirstDevice";
+                                               process_model(myWeather);

                         if (SERIALIZE(&destination, &destinationSize, myWeather->DeviceId, myWeather->WindSpeed, myWeather->Temperature, myWeather->Humidity) != CODEFIRST_OK)
                         {

otherfile.h:

// Define the Model
#include "serializer.h"
BEGIN_NAMESPACE(WeatherStation);

DECLARE_MODEL(ContosoAnemometer,
WITH_DATA(ascii_char_ptr, DeviceId),
WITH_DATA(int, WindSpeed),
WITH_DATA(float, Temperature),
WITH_DATA(float, Humidity),
WITH_ACTION(TurnFanOn),
WITH_ACTION(TurnFanOff),
WITH_ACTION(SetAirResistance, int, Position)
);

END_NAMESPACE(WeatherStation);

void process_model(ContosoAnemometer *myWeather);

otherfile.c:

#include "otherfile.h"

void process_model(ContosoAnemometer *myWeather) {
    int avgWindSpeed = 10;
    float minTemperature = 20.0;
    float minHumidity = 60.0;

    myWeather->WindSpeed = avgWindSpeed + (rand() % 4 + 2);
    myWeather->Temperature = minTemperature + (rand() % 10);
    myWeather->Humidity = minHumidity + (rand() % 20);
}

有没有办法在多个文件中使用序列化程序模型?

请随时向我询问更多信息。现在我不太确定哪些信息与此 post 相关。前段时间我对 mqtt 序列化程序示例进行了严格的尝试,但据我所知,我遇到了同样的错误。如果你不能模块化你的代码并且只有一个包含几乎所有内容的整体文件,那真的很乱。

海湾合作委员会: gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609

OS: 4.4.0-97-generic #120-Ubuntu SMP 9 月 19 日星期二 17:28:18 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

您不能重用模型,但可以重用数据结构。这可以帮助您重用多达 80% 的定义。 您可以在单独的文件中将 JSON 结构设计为一组 DECLARE_STRUCT,如下所示:

DECLARE_STRUCT(MyCommon,
   EDM_DATE_TIME_OFFSET, datetime,
   ascii_char_ptr, deviceid, 
   ascii_char_ptr, vin,
   int32_t, message_id, 
   int32_t, request_messageid 
);

之后您可以使用#include 为 С 文件中的不同模型重用 DECLARE_STRUCT:

BEGIN_NAMESPACE(cctcp);
 #include "MyCommon_json.inc"
DECLARE_MODEL(Message,
  WITH_DATA(EDM_GUID, edge_message_id),  
  WITH_DATA(int8_t, message_type),   
   WITH_DATA(MyCommon, tcu_common)
);