<< 点击显示目录 >> 主页 exOS使用助手 > exOS Automation Help > Development > Programming > exOS Communication API reference (exos_api.h) > exos_dataset_handle_t |
数据集句柄
typedef enum
{
EXOS_DATASET_SUBSCRIBE = 1,
EXOS_DATASET_PUBLISH = 16
} EXOS_DATASET_TYPE;
typedef struct exos_dataset_handle exos_dataset_handle_t;
struct exos_dataset_handle
{
char *name;
EXOS_DATASET_TYPE type;
exos_datamodel_handle_t *datamodel;
void *data;
size_t size;
EXOS_ERROR_CODE error;
EXOS_CONNECTION_STATE connection_state;
exos_send_buffer_info_t send_buffer;
int32_t nettime;
long user_tag;
void *user_context;
exos_dataset_event_cb dataset_event_callback;
void *_reserved[8];
exos_dataset_private_t _private;
};
•name:(只读)与 exos_dataset_init() 函数 中设置的 browse_name 对应 ,它是数据模型结构中成员的名称。更多信息请参阅 exos_dataset_init()
•type:(只读)用户可以订阅或发布数据集。在 exos_dataset_connect() 中 定义了数据集的 "方向"(EXOS_DATASET_PUBLISH 或 EXOS_DATASET_SUBSCRIBE)。也可以通过 EXOS_DATASET_PUBLISH + EXOS_DATASET_SUBSCRIBE 来定义双向数据集。
•datamodel:(只读)指向数据集所连接的数据模型句柄的指针。该指针可用于多种用途,例如访问数据模型的用户上下文(user_context),这样就不必为所有附加数据集定义相同的用户上下文(user_context)。例如
typedef struct {
...
} application_info_t;
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
if(dataset->datamodel->user_context)
{
//access the referenced user_context here
application_info_t *application = (application_info_t *)dataset->datamodel->user_context;
application->dataset_events ++;
...
}
}
int main(int argc, char *argc[])
{
application_info_t myapplication = {};
exos_datamodel_handle_t mydatamodel;
exos_dataset_handle_t mydataset;
exos_datamodel_init(&mydatamodel, "MyApplication", "MyApplication1");
exos_dataset_init(&mydataset, &mydatamodel, "Value1", &myapplication.val1, sizeof(myapplication.val1));
mydatamodel.user_context = &myapplication; //set the reference here..
exos_datamodel_connect_myapplication(&mydatamodel, NULL);
exos_dataset_connect(&val1, EXOS_DATASET_SUBSCRIBE, datasetEvent);
...
•data:(只读)指向 exOS API 使用的数据区的指针,并通过 exos_dataset_init()初始化 。 可以对该数据区进行读写操作,这基本上意味着要写入传递给 exos_dataset_init()的区域(或者说变量) 。例如
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
switch (event_type)
{
case EXOS_DATASET_EVENT_UPDATED:
if (0 == strcmp(dataset->name, "ResetXY"))
{
bool *resetxy = (bool *)dataset->data;
if(*resetxy)
{
...
}
..
•size:(只读)传递给 exos_dataset_init()的数据区域的大小 。现在, exos_dataset_init() 或 exos_dataset_connect不会检查 大小,但如果给某个浏览名称的大小与结构成员大小不匹配, 数据集消息路由器就 会向数据集发送 EXOS_STATE_ABORTED 事件,并带有错误 EXOS_ERROR_BAD_DATASET_SIZE。换句话说,只要数据集达到 EXOS_STATE_CONNECTED,就可以放心地认为目标变量的大小是正确的。
•error:(读取/重置)如果数据集收到 EXOS_STATE_ABORTED 事件,错误成员将被设置为相应的错误编号。该错误仅在 EXOS_STATE_ABORTED 事件中有效,但仍会被设置,用户可根据需要重置该错误。
最常见的错误可能是 EXOS_ERROR_CODE_BUFFER_OVERFLOW,这是因为发布的数据集数量超过了缓冲区的大小。 有关详情,请参阅 预定义缓冲区。
•connection_state:(只读)当前数据集的状态。数据集通常会跟随数据模型的状态,也就是说,如果数据模型断开连接,数据集也会断开连接。只要数据集没有出错,数据集就会跟随数据模型的 connection_state 到 EXOS_STATE_CONNECTED 和 EXOS_STATE_OPERATIONAL。如果发生错误(缓冲区溢出或类似情况),数据集的连接状态可能是 EXOS_STATE_ABORTED,而数据模型仍处于 EXOS_STATE_OPERATIONAL。
•send_buffer:(只读)在 EXOS_DATASET_EVENT_PUBLISHED 或 EXOS_DATASET_EVENT_DELIVERED 事件中接收到的 EXOS_DATASET_PUBLISH 类型数据集的缓冲区信息。该信息可用于避免缓冲区溢出。 有关当前缓冲区大小的更多信息,请参阅 预定义缓冲区 。示例
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
switch (event_type)
{
case EXOS_DATASET_EVENT_PUBLISHED:
VERBOSE("dataset %s published! queue size free:%i", dataset->name, dataset->send_buffer.free);
break;
osize: 该数据集的API 发送缓冲区的当前大小(数据集数
oused: API 发送缓冲区 队列中数据集的数量
ofree: API 发送缓冲区 队列中的空位数
•nettime:(只读)AR 运行时使用 NETTIME 同步系统中的所有现场总线设备。在 Linux 和 AR 中,可通过 exos_datamodel_get_nettime()获取 AR NETTIME 的同步版本 。每个已发布的数据集都附有相应的 NETTIME。
在 EXOS_DATASET_EVENT_UPDATED 事件中,数据集的 nettime 成员会根据发布者当前的 NETTIME 进行更新。这样就可以确定传输的延迟时间等:
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
switch (event_type)
{
case EXOS_DATASET_EVENT_UPDATED:
VERBOSE("dataset %s updated! latency (us):%i", dataset->name, (exos_datamodel_get_nettime(dataset->datamodel, NULL) - dataset->nettime));
•user_tag:(读/写)user_tag 可以用来设置一个用户特定的值或常量,以便日后识别数据集。exOS 允许每个数据集为其事件声明一个单独的回调,但在大多数情况下,将同一个事件回调连接到多个数据集是有意义的。为了知道当前哪个数据集处于事件回调中,可以使用 user_tag 标签,例如
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
switch (event_type)
{
case EXOS_DATASET_EVENT_UPDATED:
{
VERBOSE("dataset %s changed!", dataset->name);
//read out the user_tag here
switch (dataset->user_tag)
{
case VALUE_CONFIG:
{
SUCCESS("dataset config changed, check limits and respond to server");
WaterTankHeaterConfig *config = dataset->data;
...
int main()
{
...
EXOS_ASSERT_OK(exos_dataset_init(&config, &watertank, "HeaterConfig", &data.HeaterConfig, sizeof(data.HeaterConfig)));
config.user_tag = VALUE_CONFIG; // set the user tag here
当然,如果需要,user_tag 也可以用来存储其他附加值。
•user_context:(读/写)user_context 可用于存储指向结构或类的用户特定指针,类似于 exos_datamodel_handle_t 中的 user_context 。例如,一旦收到数据集,就应立即发布确认数据集:
static void datasetEvent(exos_dataset_handle_t *value, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
switch (event_type)
{
case EXOS_DATASET_EVENT_UPDATED:
if (0 == strcmp(value->name, "Buffer"))
{
BigDataBuffer *buffer = (BigDataBuffer *)value->data;
//update the data assigned to the "ack" dataset
buffer->Ack.Id = buffer->Id;
buffer->Ack.Latency = exos_datamodel_get_nettime(value->datamodel, NULL) - value->nettime;
//retrieve the "ack" dataset handle via the user_context and publish the value
exos_dataset_handle_t *ack_value = value->user_context;
exos_dataset_publish(ack_value);
}
...
int main()
{
...
exos_dataset_handle_t buffer;
exos_dataset_handle_t buffer_ack;
EXOS_ASSERT_OK(exos_dataset_init(&buffer_ack, &bigdata, "Buffer.Ack", &data.Buffer.Ack, sizeof(data.Buffer.Ack)));
EXOS_ASSERT_OK(exos_dataset_init(&buffer, &bigdata, "Buffer", &data.Buffer, sizeof(data.Buffer)));
buffer.user_context = &buffer_ack; //assign the "ack" dataset to the user_context of the "Buffer"
如果所有数据集都需要引用一个特定对象,那么使用数据模型的 user_context 并通过数据集中的数据模型指针进行引用(例如)会更合理:
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
//retrive the WaterTankCyclic instance from the dataset via the datamodel
struct WaterTankCyclic *inst = (struct WaterTankCyclic *)dataset->datamodel->user_context;
...
_BUR_PUBLIC void WaterTankCyclic(struct WaterTankCyclic *inst)
{
...
//the user context of the datamodel points to the WaterTankCyclic instance
watertank->user_context = inst;
•dataset_event_callback (只读)指向数据集 回调的 指针 ,可用于 触发自己的回调。例如,如果数据集在连接后应该立即接收 EXOS_DATASET_EVENT_UPDATED 事件,用户可以选择手动触发该事件。即使 EXOS_DATASET_EVENT_CONECTION_CHANGED = EXOS_STATE_CONNECTED 会更新数据集的值(存储在数据指针中),exOS API 也不会触发已连接值的初始 EXOS_DATASET_EVENT_UPDATED 事件,而这里的净时间可能无效,即与之前的发布不对应(除非该值实际上是在之前的连接中发布的)。在这种情况下,可以使用 user_tag 发出信号。
For example:
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
switch (event_type)
{
case EXOS_DATASET_EVENT_UPDATED:
if(NETTIME_NOT_VALID == dataset->user_tag)
{
INFO("dataset %s connected and updated!", dataset->name);
dataset->user_tag = 0;
}
else
{
VERBOSE("dataset %s updated! latency (us):%i", dataset->name, (exos_datamodel_get_nettime(dataset->datamodel, NULL) - dataset->nettime));
}
if (0 == strcmp(dataset->name, "ResetXY"))
{
bool *resetxy = (bool *)dataset->data;
exos_dataset_handle_t *move_val = (exos_dataset_handle_t *)dataset->user_context;
if (move_val)
{
MouseMovement *movement = move_val->data;
if (movement)
{
movement->X = 0;
movement->Y = 0;
INFO("Mouse Coordinates Reset!");
exos_dataset_publish(move_val);
}
}
}
break;
case EXOS_DATASET_EVENT_CONNECTION_CHANGED:
INFO("dataset %s changed state to %s", dataset->name, exos_get_state_string(dataset->connection_state));
switch (dataset->connection_state)
{
case EXOS_STATE_DISCONNECTED:
break;
case EXOS_STATE_CONNECTED:
//call the dataset changed event to update the dataset when connected
dataset->user_tag = NETTIME_NOT_VALID; //inform the event that the nettime isnt valid
datasetEvent(dataset, EXOS_DATASET_EVENT_UPDATED, info);
所有数据集句柄都应使用 exos_dataset_init() 函数进行初始化 。
由于句柄会在整个应用程序中使用,因此用户程序必须存储 exos_dataset_handle_t。这意味着要确保 exos_dataset_handle_t 不会超出作用域。
好:
int main(int argc, char *argc[])
{
...
//value is on the stack, within the scope
exos_dataset_handle_t counter;
exos_dataset_init(&counter, &myartefact, "Counter", &interface.Counter, sizeof(interface.Counter));
...
while(true)
{
...
坏:
exos_dataset_handle_t *makeBadDataset(void)
{
exos_artefact_handle_t myartefact; //no good!, your artefact will be lost in space!
exos_artefact_init(&myartefact, "MyApplication");
exos_dataset_handle_t counter;
exos_dataset_init(&counter, &myartefact, "Counter", &interface.Counter, sizeof(interface.Counter));
return &counter; //OH NO! lost in space!
}
int main(int argc, char *argc[])
{
exos_dataset_handle_t *cnt = makeBadDataset();
//normally the usage of cnt from now on should give you a EXOS_ERROR_BAD_VALUE_HANDLE,
//as the stack is likely to be filled with other values
...
此外, exos_dataset_handle_t 还有几个可以读写的成员。在初始化该结构的成员时,应 在 调用 exos_dataset_init()之后 进行
好:
exos_dataset_handle_t counter;
exos_dataset_init(&counter, &myartefact, "Counter", &interface.Counter, sizeof(interface.Counter));
counter.user_tag = VARS_COUNTER;
...
坏:
exos_dataset_handle_t counter;
counter.user_tag = VARS_COUNTER; //BAD!! this wont work as the structure is initialized (reset) in the next line.
exos_dataset_init(&counter, &myartefact, "Counter", &interface.Counter, sizeof(interface.Counter));
...
The dataset handle
typedef enum
{
EXOS_DATASET_SUBSCRIBE = 1,
EXOS_DATASET_PUBLISH = 16
} EXOS_DATASET_TYPE;
typedef struct exos_dataset_handle exos_dataset_handle_t;
struct exos_dataset_handle
{
char *name;
EXOS_DATASET_TYPE type;
exos_datamodel_handle_t *datamodel;
void *data;
size_t size;
EXOS_ERROR_CODE error;
EXOS_CONNECTION_STATE connection_state;
exos_send_buffer_info_t send_buffer;
int32_t nettime;
long user_tag;
void *user_context;
exos_dataset_event_cb dataset_event_callback;
void *_reserved[8];
exos_dataset_private_t _private;
};
•name: (read only) This corresponds to the browse_name set in the exos_dataset_init() function, which is the name of the member within the datamodel structure. See more on this under exos_dataset_init()
•type: (read only) A user can subscribe or publish datasets. In the exos_dataset_connect() the "direction" of the dataset is defined (EXOS_DATASET_PUBLISH or EXOS_DATASET_SUBSCRIBE). It is also possible to define biderectional datasets via EXOS_DATASET_PUBLISH + EXOS_DATASET_SUBSCRIBE.
•datamodel: (read only) Pointer to the datamodel handle that the dataset is attached to. This can be used for various reasons, for example to access the user_context of the datamodel, so that the same user_context does not have to be defined for all attached datasets. For example
typedef struct {
...
} application_info_t;
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
if(dataset->datamodel->user_context)
{
//access the referenced user_context here
application_info_t *application = (application_info_t *)dataset->datamodel->user_context;
application->dataset_events ++;
...
}
}
int main(int argc, char *argc[])
{
application_info_t myapplication = {};
exos_datamodel_handle_t mydatamodel;
exos_dataset_handle_t mydataset;
exos_datamodel_init(&mydatamodel, "MyApplication", "MyApplication1");
exos_dataset_init(&mydataset, &mydatamodel, "Value1", &myapplication.val1, sizeof(myapplication.val1));
mydatamodel.user_context = &myapplication; //set the reference here..
exos_datamodel_connect_myapplication(&mydatamodel, NULL);
exos_dataset_connect(&val1, EXOS_DATASET_SUBSCRIBE, datasetEvent);
...
•data: (read only) Pointer to the data area used by the exOS API and initialized with exos_dataset_init(). It is possible to read and write to this data area, which basically means writing to the area (or rather variable) passed to the exos_dataset_init(). For example:
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
switch (event_type)
{
case EXOS_DATASET_EVENT_UPDATED:
if (0 == strcmp(dataset->name, "ResetXY"))
{
bool *resetxy = (bool *)dataset->data;
if(*resetxy)
{
...
}
..
•size: (read only) Size of the data area passed to the exos_dataset_init(). Now, the size is not checked in the exos_dataset_init() or the exos_dataset_connect, but if a size is given to a certain browse name which does not match the structure member size, the Dataset Message Router will send an EXOS_STATE_ABORTED event to the dataset with error EXOS_ERROR_BAD_DATASET_SIZE. In other words, as soon as the dataset has reached EXOS_STATE_CONNECTED, the size can be safely assumed as the correct size for the target variable.
•error: (read / reset) In case the dataset receives an EXOS_STATE_ABORTED event, the error member is set to the according error number. The error is only valid within the EXOS_STATE_ABORTED but remains set, and it is up to the user to reset this error if needed.
The most common error is probably EXOS_ERROR_CODE_BUFFER_OVERFLOW which comes in case the amount of published datasets exceed the buffer sizes. See Predefined buffers for more on this.
•connection_state: (read only) state of the current dataset. Datasets usually follow the state of the datamodel, meaning if a datamodel get disconnected, so will the datasets. As long as no error occurs on the dataset, the dataset follows the datamodel connection_state to EXOS_STATE_CONNECTED and EXOS_STATE_OPERATIONAL. In case of an error (buffer overflow or similar), the connection state of the dataset can be EXOS_STATE_ABORTED while the datamodel is still in EXOS_STATE_OPERATIONAL.
•send_buffer: (read only) Buffer information received for datasets of the type EXOS_DATASET_PUBLISH in the EXOS_DATASET_EVENT_PUBLISHED or EXOS_DATASET_EVENT_DELIVERED event. This information can be used to avoid buffer overflows. See Predefined buffers for more on the current buffer sizes. Example:
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
switch (event_type)
{
case EXOS_DATASET_EVENT_PUBLISHED:
VERBOSE("dataset %s published! queue size free:%i", dataset->name, dataset->send_buffer.free);
break;
osize: current size (number of datasets) of the API send buffer for this dataset
oused: number of datasets in the API send buffer queue
ofree: number of empty slots in the API send buffer queue
•nettime: (read only) Automation Runtime uses the NETTIME to synchronize all fielbus devices on a system. A synchronized version of the AR NETTIME is available in Linux and AR via exos_datamodel_get_nettime(). For every dataset that is published, a corresponding NETTIME is attached.
The nettime member of a dataset is updated in the EXOS_DATASET_EVENT_UPDATED event, with the current NETTIME of the publisher. With this it is possible to determine the latency of the transmission, for example:
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
switch (event_type)
{
case EXOS_DATASET_EVENT_UPDATED:
VERBOSE("dataset %s updated! latency (us):%i", dataset->name, (exos_datamodel_get_nettime(dataset->datamodel, NULL) - dataset->nettime));
•user_tag: (read / write) The user_tag can be used to set a user-specific value or constant to later identify the dataset. exOS allows every dataset to declare an individual callback for its events, but in most cases it makes sense to connect the same event callback to several datasets. In order to know which dataset is currently in the event callback, the user_tag can be used, for example
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
switch (event_type)
{
case EXOS_DATASET_EVENT_UPDATED:
{
VERBOSE("dataset %s changed!", dataset->name);
//read out the user_tag here
switch (dataset->user_tag)
{
case VALUE_CONFIG:
{
SUCCESS("dataset config changed, check limits and respond to server");
WaterTankHeaterConfig *config = dataset->data;
...
int main()
{
...
EXOS_ASSERT_OK(exos_dataset_init(&config, &watertank, "HeaterConfig", &data.HeaterConfig, sizeof(data.HeaterConfig)));
config.user_tag = VALUE_CONFIG; // set the user tag here
The user_tag can of course be used for storing any other additional values if needed.
•user_context: (read / write) The user_context can be used to store user-specific pointers to structures or classes, similar to the user_context in the exos_datamodel_handle_t. For example, an acknowledgement dataset should be published as soon as a dataset is received:
static void datasetEvent(exos_dataset_handle_t *value, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
switch (event_type)
{
case EXOS_DATASET_EVENT_UPDATED:
if (0 == strcmp(value->name, "Buffer"))
{
BigDataBuffer *buffer = (BigDataBuffer *)value->data;
//update the data assigned to the "ack" dataset
buffer->Ack.Id = buffer->Id;
buffer->Ack.Latency = exos_datamodel_get_nettime(value->datamodel, NULL) - value->nettime;
//retrieve the "ack" dataset handle via the user_context and publish the value
exos_dataset_handle_t *ack_value = value->user_context;
exos_dataset_publish(ack_value);
}
...
int main()
{
...
exos_dataset_handle_t buffer;
exos_dataset_handle_t buffer_ack;
EXOS_ASSERT_OK(exos_dataset_init(&buffer_ack, &bigdata, "Buffer.Ack", &data.Buffer.Ack, sizeof(data.Buffer.Ack)));
EXOS_ASSERT_OK(exos_dataset_init(&buffer, &bigdata, "Buffer", &data.Buffer, sizeof(data.Buffer)));
buffer.user_context = &buffer_ack; //assign the "ack" dataset to the user_context of the "Buffer"
If all datasets need to reference a specific object, it makes more sense to use the user_context of the datamodel and instead reference this via the datamodel pointer in the dataset, for example:
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
//retrive the WaterTankCyclic instance from the dataset via the datamodel
struct WaterTankCyclic *inst = (struct WaterTankCyclic *)dataset->datamodel->user_context;
...
_BUR_PUBLIC void WaterTankCyclic(struct WaterTankCyclic *inst)
{
...
//the user context of the datamodel points to the WaterTankCyclic instance
watertank->user_context = inst;
•dataset_event_callback (read only) pointer to the dataset callback that can be used to trigger own callbacks. For example, if the dataset should receive an EXOS_DATASET_EVENT_UPDATED event as soon as it is connected, the user can choose to trigger this manually. The exOS API will not trigger initial EXOS_DATASET_EVENT_UPDATED events for connected values, even though the EXOS_DATASET_EVENT_CONNECTION_CHANGED = EXOS_STATE_CONNECTED will update the value of the dataset (stored in the data pointer), whereas here the nettime is possibly not valid, i.e. does not correspond to a previous publish (unless the value was in fact published in a previous connection). In that situation, the user_tag can be used to signal this.
For example:
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
switch (event_type)
{
case EXOS_DATASET_EVENT_UPDATED:
if(NETTIME_NOT_VALID == dataset->user_tag)
{
INFO("dataset %s connected and updated!", dataset->name);
dataset->user_tag = 0;
}
else
{
VERBOSE("dataset %s updated! latency (us):%i", dataset->name, (exos_datamodel_get_nettime(dataset->datamodel, NULL) - dataset->nettime));
}
if (0 == strcmp(dataset->name, "ResetXY"))
{
bool *resetxy = (bool *)dataset->data;
exos_dataset_handle_t *move_val = (exos_dataset_handle_t *)dataset->user_context;
if (move_val)
{
MouseMovement *movement = move_val->data;
if (movement)
{
movement->X = 0;
movement->Y = 0;
INFO("Mouse Coordinates Reset!");
exos_dataset_publish(move_val);
}
}
}
break;
case EXOS_DATASET_EVENT_CONNECTION_CHANGED:
INFO("dataset %s changed state to %s", dataset->name, exos_get_state_string(dataset->connection_state));
switch (dataset->connection_state)
{
case EXOS_STATE_DISCONNECTED:
break;
case EXOS_STATE_CONNECTED:
//call the dataset changed event to update the dataset when connected
dataset->user_tag = NETTIME_NOT_VALID; //inform the event that the nettime isnt valid
datasetEvent(dataset, EXOS_DATASET_EVENT_UPDATED, info);
All dataset handles should be initialized with the exos_dataset_init() function.
As the handle is used throughout the entire application, it is important for the user program to store the exos_dataset_handle_t. This means ensuring that the exos_dataset_handle_t never gets out of scope.
Good:
int main(int argc, char *argc[])
{
...
//value is on the stack, within the scope
exos_dataset_handle_t counter;
exos_dataset_init(&counter, &myartefact, "Counter", &interface.Counter, sizeof(interface.Counter));
...
while(true)
{
...
Bad:
exos_dataset_handle_t *makeBadDataset(void)
{
exos_artefact_handle_t myartefact; //no good!, your artefact will be lost in space!
exos_artefact_init(&myartefact, "MyApplication");
exos_dataset_handle_t counter;
exos_dataset_init(&counter, &myartefact, "Counter", &interface.Counter, sizeof(interface.Counter));
return &counter; //OH NO! lost in space!
}
int main(int argc, char *argc[])
{
exos_dataset_handle_t *cnt = makeBadDataset();
//normally the usage of cnt from now on should give you a EXOS_ERROR_BAD_VALUE_HANDLE,
//as the stack is likely to be filled with other values
...
Furthermore, the exos_dataset_handle_t has several members that can be read and written to. When intializing members of the structure, this should be done after calling the exos_dataset_init()
Good:
exos_dataset_handle_t counter;
exos_dataset_init(&counter, &myartefact, "Counter", &interface.Counter, sizeof(interface.Counter));
counter.user_tag = VARS_COUNTER;
...
Bad:
exos_dataset_handle_t counter;
counter.user_tag = VARS_COUNTER; //BAD!! this wont work as the structure is initialized (reset) in the next line.
exos_dataset_init(&counter, &myartefact, "Counter", &interface.Counter, sizeof(interface.Counter));
...