diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 25c41dc..afc09fc 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -10,7 +10,8 @@ set(EXAMPLE_SOURCES stream_reader_read_in_loop.c read_with_formatted_timestamps.c print_data_descriptor_and_calculater_sample_rate.c - create_and_read_sample_rate_buffers.c) + create_and_read_sample_rate_buffers.c + custom_struct_type_conversion.c) foreach(src ${EXAMPLE_SOURCES}) diff --git a/examples/custom_struct_type_conversion.c b/examples/custom_struct_type_conversion.c new file mode 100644 index 0000000..264f289 --- /dev/null +++ b/examples/custom_struct_type_conversion.c @@ -0,0 +1,224 @@ +/* + * + */ +#include + + // Custom struct type +struct Coordinates +{ + int64_t x; + int64_t y; + int64_t z; +}; + +// Adds Coodinates struct and ComponentStatusTypeEnum to types in Type Manager +void addCoordinateStructToTypeManager(daqContext* context) +{ + daqTypeManager* typeManager = NULL; + daqContext_getTypeManager(context, &typeManager); + + daqList* names = NULL; + daqList_createList(&names); + + daqString* temp = daq_toDaqString("x"); + + daqList_pushBack(names, (daqBaseObject*)temp); + daqReleaseRef(temp); + temp = daq_toDaqString("y"); + daqList_pushBack(names, (daqBaseObject*) temp); + daqReleaseRef(temp); + temp = daq_toDaqString("z"); + daqList_pushBack(names, (daqBaseObject*)temp); + daqReleaseRef(temp); + + daqSimpleType* simpleType = NULL; + daqSimpleType_createSimpleType(&simpleType, daqCtInt); + + daqList* types = NULL; + daqList_createList(&types); + daqList_pushBack(types, simpleType); + daqList_pushBack(types, simpleType); + daqList_pushBack(types, simpleType); + daqReleaseRef(simpleType); + + daqStructType* newType = NULL; + daqStructType_createStructTypeNoDefaults(&newType, daq_toDaqString("DAQ_Coordinates"), names, types); + + daqTypeManager_addType(typeManager, (daqType*) newType); + daqReleaseRef(newType); + daqReleaseRef(names); + + daqBool check = False; + daqTypeManager_hasType(typeManager, daq_toDaqString("DAQ_Coordinates"), &check); + + daqBool enumCheck = False; + daqTypeManager_hasType(typeManager, daq_toDaqString("DAQ_ComponentStatusTypeEnum"), &enumCheck); + + if (check && enumCheck) + printf("\nNew types added.\n"); + else + printf("\nFailed to add new types.\n"); + + daqReleaseRef(types); + daqReleaseRef(names); + daqReleaseRef(typeManager); +} + +// Struct conversion +/* + * Conversion from and to daqStruct objects to C style structs. + * Warning: These types of conversions require prior knowledge of + * the struct structure and its definition in C. For conversion + * from C to openDAQ a pointer to the TypeManager is needed because + * of the way openDAQ structs are implemented. + */ +struct Coordinates daq_fromDaqCoordinates(daqStruct* daq) +{ + struct Coordinates native = { 0,0,0 }; + + daqBaseObject* tempObj = NULL; + daqBaseObject* tempMid = NULL; + + daqString* temp = daq_toDaqString("x"); + daqStruct_get(daq, temp, tempObj); + tempMid = daqQueryInterfacePtr(tempObj, DAQ_INTEGER_INTF_ID); + native.x = daq_fromDaqInteger((daqInteger*) tempMid); + daqReleaseRef(tempMid); + daqReleaseRef(tempObj); + daqReleaseRef(temp); + + temp = daq_toDaqString("y"); + daqStruct_get(daq, temp, tempObj); + tempMid = daqQueryInterfacePtr(tempObj, DAQ_INTEGER_INTF_ID); + native.y = daq_fromDaqInteger((daqInteger*) tempMid); + daqReleaseRef(tempMid); + daqReleaseRef(tempObj); + daqReleaseRef(temp); + + temp = daq_toDaqString("z"); + daqStruct_get(daq, temp, tempObj); + tempMid = daqQueryInterfacePtr(tempObj, DAQ_INTEGER_INTF_ID); + native.z = daq_fromDaqInteger((daqInteger*) tempMid); + daqReleaseRef(tempMid); + daqReleaseRef(tempObj); + daqReleaseRef(temp); + + return native; +} + +daqStruct* daq_toDaqCoordinates(struct Coordinates native, daqTypeManager* typeManager) +{ + daqStructBuilder* builder = NULL; + daqStructBuilder_createStructBuilder(&builder, daq_toDaqString("DAQ_Coordinates"), typeManager); + + daqString* temp = NULL; + daqInteger* tempInt = NULL; + if (0) + { + // We can set values in the struct either via directly assigning them to the + // corresponding struct values or adding them in the correct sequence + // to a daqList and setting the list. + daqList* values = NULL; + daqList_createList(&values); + + tempInt = daq_toDaqInteger(native.x); + daqList_pushBack(values, (daqBaseObject*) tempInt); + daqReleaseRef(tempInt); + tempInt = daq_toDaqInteger(native.y); + daqList_pushBack(values, (daqBaseObject*) tempInt); + daqReleaseRef(tempInt); + tempInt = daq_toDaqInteger(native.z); + daqList_pushBack(values, (daqBaseObject*) tempInt); + daqReleaseRef(tempInt); + + daqStructBuilder_setFieldValues(builder, values); + daqReleaseRef(values); + } + else + { + + temp = daq_toDaqString("x"); + tempInt = daq_toDaqInteger(native.x); + daqStructBuilder_set(builder, temp, (daqBaseObject*) tempInt); + daqReleaseRef(temp); + daqReleaseRef(tempInt); + + temp = daq_toDaqString("y"); + tempInt = daq_toDaqInteger(native.y); + daqStructBuilder_set(builder, temp, (daqBaseObject*) tempInt); + daqReleaseRef(temp); + daqReleaseRef(tempInt); + + temp = daq_toDaqString("z"); + tempInt = daq_toDaqInteger(native.z); + daqStructBuilder_set(builder, temp, (daqBaseObject*) tempInt); + daqReleaseRef(temp); + daqReleaseRef(tempInt); + } + daqStruct* daq = NULL; + daqStructBuilder_build(builder, &daq); + daqReleaseRef(builder); + + return daq; +} + +// Enumeration conversion +/* + * Conversion from and to openDAQ String (daqEnumeration) core type + * from C language (enum ComponentStutesTypeEnum). + * Warning: These types of conversions require prior knowledge of + * the enumeration structure and its definition in C. For conversion + * from C to openDAQ a pointer to the TypeManager is needed because + * of the way openDAQ enumeration is implemented. + */ +enum ComponentStatusTypeEnum daq_fromDaqCompStatusTypeEnum(daqEnumeration* daq) +{ + enum ComponentStatusTypeEnum native = Error; + uint8_t temp; + daqEnumeration_getIntValue(daq, &temp); + + // Sanity check + if (temp < 2) + native = temp; + + return native; +} + +daqEnumeration* daq_toCompStatusTypeEnum(enum ComponentStatusTypeEnum native, daqTypeManager* typeManager) +{ + daqEnumeration* daq = NULL; + daqInteger* tempInt = daq_toDaqInteger(native); + daqString* temp = daq_toDaqString("ComponentStatusType"); + + daqEnumeration_createEnumerationWithIntValue(&daq, temp, tempInt, typeManager); + + daqReleaseRef(temp); + daqReleaseRef(tempInt); + return daq; +} + +int main() +{ + daqInstance* simulatorInstance = NULL; + setupSimulator(&simulatorInstance); + + daqInstance* instance = NULL; + daqDevice* simulator = NULL; + addSimulator(&simulator, &instance); + + daqContext* context = NULL; + daqComponent_getContext((daqComponent*) instance, &context); + addCoordinateStructToTypeManager(context); + daqReleaseRef(context); + + daqStructBuilder* builder = NULL; + + // Set a new property Object that is the new type and write its value and read it + // Might need to set up a custom simulator that will have daq_coordinates as a field + + daqReleaseRef(simulator); + daqReleaseRef(instance); + daqReleaseRef(simulatorInstance); + + return 0; +} \ No newline at end of file diff --git a/examples/util_headers/daq_c_conversions.h b/examples/util_headers/daq_c_conversions.h new file mode 100644 index 0000000..2d5a279 --- /dev/null +++ b/examples/util_headers/daq_c_conversions.h @@ -0,0 +1,184 @@ +#include + +// Core struct type +struct ComplexNumber +{ + double real; + double imaginary; +}; + +// Core struct type +struct Range +{ + double min; + double max; +}; + +// Standard enum +enum ComponentStatusTypeEnum +{ + Error = 0, + Ok, + Warning +}; + +// Int conversion +/* + * The following two funtions represent the conversion between the openDAQ native + * daqInt type and its coresponding C integer type. + */ +daqInt daq_fromDaqInteger(daqInteger* daq); +daqInteger* daq_toDaqInteger(daqInt native); + +// String conversion +/* + * Conversion from and to openDAQ String (daqString) core type + * from C language (const char*). The function that converts to native C return a non-owning pointer. + * Precautions should be taken, when using the received pointer. + */ +char* daq_fromDaqString(daqString* daq); +daqString* daq_toDaqString(const char* native); + +// Bool conversion +/* + * Conversion from and to openDAQ Boolean (daqString) core type from C language (uint8_t). + */ +uint8_t daq_fromDaqBoolean(daqBoolean* daq); +daqBoolean* daq_toDaqBoolean(uint8_t native); + +// Float conversion +/* + *Conversion from and to openDAQ String (daqFloat) core type from C language (double). + */ +daqFloat daq_fromDaqObject(daqFloatObject* daq); +daqFloatObject* daq_toDaqFloatObject(daqFloat native); + +// Complex number conversion +/* + * Conversion from and to openDAQ Complex (daqComplex) core type + * from C language (struct ComplexNumber). + */ +struct ComplexNumber daq_fromDaqComplex(daqComplexNumber* daq); +daqComplexNumber* daq_toDaqComplex(struct ComplexNumber* native); + +// Range conversion +/* + * Conversion from and to openDAQ String (daqRange) core type + * from C language (struct Range). + */ +struct Range daq_fromDaqRange(daqRange* daq); +daqRange* daq_toDaqRange(struct Range native); + +daqInt daq_fromDaqInteger(daqInteger* daq) +{ + daqInt native = 0; + daqInteger_getValue(daq, &native); + return native; +} + +daqInteger* daq_toDaqInteger(daqInt native) +{ + daqInteger* daq = NULL; + daqInteger_createInteger(&daq, native); + return daq; +} + +char* daq_fromDaqString(daqString* daq) +{ + char* native = NULL; + daqString_getCharPtr(daq, &native); + return native; +} + +daqString* daq_toDaqString(const char* native) +{ + daqString* daq = NULL; + daqString_createString(&daq, native); + return daq; +} + +uint8_t daq_fromDaqBoolean(daqBoolean* daq) +{ + uint8_t native = 0; + daqBoolean_getValue(daq, &native); + return native; +} + +daqBoolean* daq_toDaqBoolean(uint8_t native) +{ + daqBoolean* daq = NULL; + daqBoolean_createBoolean(&daq, native); + return daq; +} + +daqFloat daq_fromDaqObject(daqFloatObject* daq) +{ + daqFloat native = 0; + daqFloatObject_getValue(daq, &native); + return native; +} + +daqFloatObject* daq_toDaqFloatObject(daqFloat native) +{ + daqFloatObject* daq = 0; + daqFloatObject_createFloatObject(&daq, native); + return daq; +} + +struct ComplexNumber daq_fromDaqComplex(daqComplexNumber* daq) +{ + struct ComplexNumber native = {0, 0}; + double tempDouble= 0; + daqComplexNumber_getReal(daq, &tempDouble); + native.real = tempDouble; + daqComplexNumber_getImaginary(daq, &tempDouble); + native.imaginary = tempDouble; + return native; +} + +daqComplexNumber* daq_toDaqComplex(struct ComplexNumber* native) +{ + daqComplexNumber* daq = NULL; + daqComplexNumber_createComplexNumber(&daq, native->real, native->imaginary); + return daq; +} + +struct Range daq_fromDaqRange(daqRange* daq) +{ + struct Range native = {0, 0}; + daqNumber* temp; + daqRange_getLowValue(daq, &temp); + double intermmidiate = 0; + daqNumber_getFloatValue(temp, &intermmidiate); + native.min = intermmidiate; + daqReleaseRef(temp); + + daqRange_getHighValue(daq, &temp); + daqNumber_getFloatValue(temp, &intermmidiate); + native.max = intermmidiate; + daqReleaseRef(temp); + return native; +} + +daqRange* daq_toDaqRange(struct Range native) +{ + daqRange* daq = NULL; + daqNumber* lowValue = NULL; + daqNumber* highValue = NULL; + + daqFloatObject* lowFloat = daq_toDaqFloatObject(native.min); + daqFloatObject* highFloat = daq_toDaqFloatObject(native.max); + + daqQueryInterface(lowFloat, DAQ_NUMBER_INTF_ID, &lowValue); + daqQueryInterface(highFloat, DAQ_NUMBER_INTF_ID, &highValue); + + daqReleaseRef(lowFloat); + daqReleaseRef(highFloat); + + // Create and populate the daqRange object + daqRange_createRange(&daq, lowValue, highValue); + + daqReleaseRef(lowValue); + daqReleaseRef(highValue); + return daq; +}