From: Jochen Kalmbach [MVP] on 23 Dec 2008 06:13 Hi Hugo! > typedef struct arg_info > { > TypeCode type; // enum > char * data_ptr; // pointer to argument data bytes > } This is almost a "variant"... The variant uses a "union" to store all data (and to save space). > This is a dynamic scenarion and requires a runtime conversion of any type to > any other, an array of function is one idea we are looking at (my earlier > example was just one of the functions, there would be LOTS of them in total) Yes. You need to write your own "conversion-routine"... VariantChangeType does the same (two "recursive" switch statements). > I looked at variants and it seems (I may be wrong) that a variant is a large > struct Almost the same as your struct... > that must be initialized and stuff, so would be an overhead given that > our data is simply a type-code and a ptr to the data bytes. You struct must also be initialized, or? In a VARIANT only the TYPECODE (vType) needs to be initialized. The same is true for your "variant"... > I mean, does the variant or some other API let me just pass type codes and > pointers to data or must I use these large variant structs? What is a "large" variant-struct? As I said: VARIANTs use a *union* which safes much space. Also it does not require a "malloc" like your struct! sizeof(VARIANT) is 16. But is can store much more than just simple-types. It can also store (recursive) arrays... But you can also implement your own variant, which will fit exactly in what you want. I do not know a "better" way... Greetings Jochen
From: Christian Kaiser on 23 Dec 2008 06:49 Well, either you use VARIANTs (and all the overhead that it requires if you don't already use them), or you need to do all that conversion stuff yourself. There's no way to find pre-done stuff if the data is defined by yourself. You could use macros to simplify writing, or even use a small script (VB, Python, Ruby, ...) to create the code for you (which is what I would do). Nevertheless, you need to do it for each data type source/destination pair to create two big nested switch() codes. Christian "Hugo gleaves(a)hotmail.com>" <hugh<underbar> wrote in message news:4B0CAD70-B6E6-4E19-93B7-0EEA0A1737C8(a)microsoft.com... > Hi Jochen > > Yes this is a runtime conversion, our API receives two structs: > > typedef struct arg_info > { > TypeCode type; // enum > char * data_ptr; // pointer to argument data bytes > } > > > The API needs to compare these two args in various ways, they could > be any > combination of signed/unsigned int, short etc as well as float, > double etc. > > For any two types, there is a single 'common' type, so for a signed > short > and a signed long, the common type is signed long (this is similar > to what a > compiler has to do). > > So we want to code stuff like: > > ConvertFromTo[arg1.type][TypeCode.ULong](arg1); > > and so on. > > This is a dynamic scenarion and requires a runtime conversion of any > type to > any other, an array of function is one idea we are looking at (my > earlier > example was just one of the functions, there would be LOTS of them > in total) > > I looked at variants and it seems (I may be wrong) that a variant is > a large > struct that must be initialized and stuff, so would be an overhead > given that > our data is simply a type-code and a ptr to the data bytes. > > I mean, does the variant or some other API let me just pass type > codes and > pointers to data or must I use these large variant structs? > > Thx > H > > > > "Jochen Kalmbach [MVP]" wrote: > >> Hi Hugo! >> >> > I therefore do stuff like this, if I want to convert a double to >> > a long: >> > >> > *((long*)(target_ptr)) = (long)(*((double*)(source_ptr))); >> > >> > Every conversion is pretty much the same, just the type names >> > vary (forget >> > about strings for now). >> >> You requested a (dynamic) *runtime* conversion... and your example >> is a >> *compile-time* conversion... >> So I don't understand what you want... >> >> >> Also VARIANTs are working perfectly with (simple/native) C. >> >> Greetings >> Jochen >>
From: Hugo gleaves on 23 Dec 2008 07:47
Hi I was wrong about variants, I see they are unions and I missed that when I glanced at the defintion, our data structs are already defined and so this is a bit of a hassle at this stage for using variants. We did opt for a macro, we now define a load of suitable named from/to functions that simply 'call' the macro and pass-in the type names required, eg: # define ConvertFromTo(S,T) (*((T*)(target)) = (T)*((S*)(source))) We then define the individual functions like this: static void ConvertUInt16ToUInt16 (void * source,void * target) {ConvertFromTo(unsigned short,unsigned short);} static void ConvertUInt16ToInt32 (void * source,void * target) {ConvertFromTo(unsigned short,long);} static void ConvertUInt16ToUInt32 (void * source,void * target) {ConvertFromTo(unsigned short,unsigned long);} static void ConvertUInt16ToInt64 (void * source,void * target) {ConvertFromTo(unsigned short,long long);} and so on. Finally we have a function that initialzies a 2D array indexed by type-code and we can then call the correct conversion by simply: convert[arg.type][dest.type](arg_ptr,dest_ptr); This will convert the data at 'arg_ptr' from 'arg.type' to 'dest.type' and put the result in 'dest_ptr'. At least this should be pretty fast... Thx H "Christian Kaiser" wrote: > Well, either you use VARIANTs (and all the overhead that it requires > if you don't already use them), or you need to do all that conversion > stuff yourself. There's no way to find pre-done stuff if the data is > defined by yourself. > > You could use macros to simplify writing, or even use a small script > (VB, Python, Ruby, ...) to create the code for you (which is what I > would do). Nevertheless, you need to do it for each data type > source/destination pair to create two big nested switch() codes. > > Christian > > "Hugo gleaves(a)hotmail.com>" <hugh<underbar> wrote in message > news:4B0CAD70-B6E6-4E19-93B7-0EEA0A1737C8(a)microsoft.com... > > Hi Jochen > > > > Yes this is a runtime conversion, our API receives two structs: > > > > typedef struct arg_info > > { > > TypeCode type; // enum > > char * data_ptr; // pointer to argument data bytes > > } > > > > > > The API needs to compare these two args in various ways, they could > > be any > > combination of signed/unsigned int, short etc as well as float, > > double etc. > > > > For any two types, there is a single 'common' type, so for a signed > > short > > and a signed long, the common type is signed long (this is similar > > to what a > > compiler has to do). > > > > So we want to code stuff like: > > > > ConvertFromTo[arg1.type][TypeCode.ULong](arg1); > > > > and so on. > > > > This is a dynamic scenarion and requires a runtime conversion of any > > type to > > any other, an array of function is one idea we are looking at (my > > earlier > > example was just one of the functions, there would be LOTS of them > > in total) > > > > I looked at variants and it seems (I may be wrong) that a variant is > > a large > > struct that must be initialized and stuff, so would be an overhead > > given that > > our data is simply a type-code and a ptr to the data bytes. > > > > I mean, does the variant or some other API let me just pass type > > codes and > > pointers to data or must I use these large variant structs? > > > > Thx > > H > > > > > > > > "Jochen Kalmbach [MVP]" wrote: > > > >> Hi Hugo! > >> > >> > I therefore do stuff like this, if I want to convert a double to > >> > a long: > >> > > >> > *((long*)(target_ptr)) = (long)(*((double*)(source_ptr))); > >> > > >> > Every conversion is pretty much the same, just the type names > >> > vary (forget > >> > about strings for now). > >> > >> You requested a (dynamic) *runtime* conversion... and your example > >> is a > >> *compile-time* conversion... > >> So I don't understand what you want... > >> > >> > >> Also VARIANTs are working perfectly with (simple/native) C. > >> > >> Greetings > >> Jochen > >> > > > |