Open maltesen opened 5 years ago
I dont understand why there is not only lsl_push_sample which maps its input data to the type defined by the channel_format defined for the corresponding streaminfo.
The push functions have to be typed and C doesn't allow function overloading. The alternative (push_sample(void* data, …)
) would be error-prone and hard to use when you want to push a different data type. The data types are all signed, but I can't recall the exact reason for it.
Your mapping is mostly correct:
lsl_push_sample_c; cft_int8 lsl_push_sample_str; cft_string lsl_push_sample_buf; cft_string lsl_push_sample_v; cft_string
Thank you very much @tstenner! This works for me as is.
However, transmitting basic data types over a serial interface is the core functionality of the library. Also typecasting is a topic where it can easily occure that errors slip through unnoticed until data is lost. Imo one of the main reasons to use a library like this is the intention to avoid bugs during typecast, serialization, de-serialization, and typecast again.
Without wanting to create much hassle and thankful that a unified protocol for lab environments like this is available at all i would respectfully like to suggest to tidy this part up (redundancy and possibility to use mismatches of channel format and push_sample function types; implementation of unsigned types; implementation of separate char, unit8 and int8 types), if time is available.
Thank you very much and have a nice day!
Just to clarify: the different functions are there to let the compiler prevent you from giving the wrong data type to a single push_sample(void*)
function. The push (and pull) functions will still check what's the stream's data type and convert, so in theory you could have an int64 stream, push a double array with push_sample_d
and retrieve the data as string array with pull_sample_s
at the other end.
Hmm i fail to see the benefit of this. To me it appears you are calling a feature what i would call a bug.
I would have expected it to work this way.: I define the type of the stream during creation of the outlet using the channel_format field. If later on i try to push a different type into the stream it throws an error. On the inlet side a 2nd party can tell by looking at the channel_format field what kind of stream this is. Pulling any other type from it is an error.
In order to add the functionality of arbitrary type casting you mentioned above to my interpretation of how it should work the user would have to typecast before and after using liblsl at his own risk. Youre implementation however does not provide the benefit that the user of the inlet can be SURE that the datatype of the stream is as advertized in the header of the stream (the channel_format field). So, in a wider sense, the inlet user can not be sure about the transmission protocol being used without knowing the sourcecode of the sender. But exactly that should be the job of the stream header, to define the protocol, the type being used, the version of the protocol, the lexicale being used.
If arbitrary typecasts at inlet and outlet inside liblsl are possible, as you describe it (that functionality is already implemented by the system using libls as mentioned above), whats the use of the channel_format field? An internal buffer size? Why would the user want to tamper with that? Is there any reason to not set it to a 64Bit type apart from maybe increasing the load of the transmission line? What happens if channel_format is set to a 8bit type and the outlet is then pushed with int32s? are the remaining 24 bits lost or does that result in 4 times as many samples? You said the push and pull functions still check the streams data type, so that would be an error if the pushed type is bitwise larger than the channel_format field?
Hello.
I do not understand the intended use of specifiing a channel_format while creating the streaminfo for an outlet and the function groups for different types like lsl_pushsample*.
there is the channel_format enum
to define which data type the outlet would use. Then there are the individual functions to push that type of data into the outlet.:
lsl_push_sample_f lsl_push_sample_d lsl_push_sample_s lsl_push_sample_i lsl_push_sample_l lsl_push_sample_c lsl_push_sample_str lsl_push_sample_buf lsl_push_sample_v
1) I dont understand why there is not only lsl_push_sample which maps its input data to the type defined by the channel_format defined for the corresponding streaminfo. This seems redundant to me. It could be intended, that i can i.e. define the channel format as cft_int16 but instead put uint16 data to perform a typecast. I doubt that this is the intended use case though, as it would be easier and cleaner to just cast uint16 to int16 directly before putting the data into the outlet.
2) I dont understand which channel_format is to be used with which lsl_push_sample function. There are 7+ channel formats but 9 different lsl_push_sample functions. A table of the mapping as i think it is correct.:
lsl_push_sample_f; cft_float32 lsl_push_sample_d; cft_double64 lsl_push_sample_s; cft_int16 lsl_push_sample_i; cft_int32 lsl_push_sample_l; cft_int64 lsl_push_sample_c; unknown lsl_push_sample_str; cft_string lsl_push_sample_buf; unknown lsl_push_sample_v; unknown unknown; cft_int8
3) I dont understand how i would transfer the basic types uint8, uint16, uint32, and uint64 (,and int8). There seems to be no channel format and no function for the unsigned integers and no functions (apart from maybe lsl_push_sample_c) for the int8 type. I could just use signed int and assume that the receiver knows that he has to cast it to unsigned int after pulling the data from the inlet, but that would be not very clean.
This should probably be one of the main chapters in the developers guide, but i couldn't find it.
Thank you very much for your time!