 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Kevin Lin Guest
|
Posted: Mon Jun 13, 2005 7:48 pm Post subject: Calculating member offset at runtime |
|
|
The problem: I want to mark certain members of a class/struct for
network serialization. Since I don't want to send the entire object
over the wire, I want to calculate the offset of a member, so I can
just grab it out of an instance, send it out, and restuff it back in.
I know the offsetof macro is a compile-time constant and works only for
POD types. But if I don't mind doing the offset calculation at
runtime, would a straightforward pointer calculation work?
struct test
{
test() : i(1) {}
int i;
};
struct test2 : public test
{
int j;
};
//Get the offset of j
size_t offset_j(test2* pTest2)
{
char* pT = (char*)(&(pTest2->j));
return pT - (char*)(pTest2);
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Larry Evans Guest
|
Posted: Mon Jun 13, 2005 10:44 pm Post subject: Re: Calculating member offset at runtime |
|
|
On 06/13/2005 02:48 PM, Kevin Lin wrote:
| Quote: | The problem: I want to mark certain members of a class/struct for
network serialization. Since I don't want to send the entire object
over the wire, I want to calculate the offset of a member, so I can
just grab it out of an instance, send it out, and restuff it back in.
I know the offsetof macro is a compile-time constant and works only for
POD types. But if I don't mind doing the offset calculation at
runtime, would a straightforward pointer calculation work?
|
You might try field_visitors library at:
http://cvs.sourceforge.net/viewcvs.py/boost-sandbox/boost-sandbox/boost/fields_visitor/
An example of its use is at:
http://boost-sandbox.sourceforge.net/vault/index.php?&direction=0&order=&directory=cppljevans/field_visitor_tests
Basicly, you wrap each field you want serialized with a wrapper class
whose CTOR records its offset from the container during creation of
a "dummy" instance of that container. Then you've got all the
information you need to serialize. The example just prints the
fields out.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Catalin Marinas Guest
|
Posted: Tue Jun 14, 2005 7:35 pm Post subject: Re: Calculating member offset at runtime |
|
|
"Kevin Lin" <kevin.ic (AT) gmail (DOT) com> wrote:
| Quote: | I know the offsetof macro is a compile-time constant and works only for
POD types. But if I don't mind doing the offset calculation at
runtime, would a straightforward pointer calculation work?
|
You can use something like this where no structure needs to be
instantiated (same implementation in the Linux kernel):
#define offset_of(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
....
offset_of(test2, j);
or (but the structure needs to be instantiated):
template <class T, class M>
unsigned long offset_of(T& structure, M& member)
{
return reinterpret_cast<unsigned long>(&member)
- reinterpret_cast<unsigned long>(&structure);
}
....
test2 t;
offset_of(t, t.j);
--
Catalin
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
wkaras@yahoo.com Guest
|
Posted: Wed Jun 15, 2005 10:50 pm Post subject: Re: Calculating member offset at runtime |
|
|
Kevin Lin wrote:
| Quote: | The problem: I want to mark certain members of a class/struct for
network serialization. Since I don't want to send the entire object
over the wire, I want to calculate the offset of a member, so I can
just grab it out of an instance, send it out, and restuff it back in.
I know the offsetof macro is a compile-time constant and works only for
POD types. But if I don't mind doing the offset calculation at
runtime, would a straightforward pointer calculation work?
struct test
{
test() : i(1) {}
int i;
};
struct test2 : public test
{
int j;
};
//Get the offset of j
size_t offset_j(test2* pTest2)
{
char* pT = (char*)(&(pTest2->j));
return pT - (char*)(pTest2);
}
|
Here is an alternate approach to the underlying problem (of
sending selected fields in a class). I doubt you'll be
able to use it verbatim, but with a little adaptation...
Here is the general header file "xmitstruct.hpp"
#include <bitset>
#include <string.h>
#define PP_CAT_(ID1, ID2) ID1##ID2
#define PP_CAT(ID1, ID2) PP_CAT_(ID1, ID2)
struct P__NAME
{
#undef X
#define X(TYPE, FIELD) TYPE FIELD;
P__FIELDLIST
#undef X
#define X(TYPE, FIELD) PP_CAT(Idx_, FIELD),
enum PP_CAT(P__NAME, _indexes)
{
P__FIELDLIST,
PP_CAT(P__NAME, _num_fields)
};
typedef bitset<PP_CAT(P__NAME, _num_fields)> Fieldset;
unsigned pack(const Fieldset &fs, char *msg)
{
char *msg_ = msg;
memcpy(msg, &fs, sizeof(fs));
msg += sizeof(fs);
#undef X
#define X(TYPE, FIELD)
if (fs[PP_CAT(Idx_, FIELD)])
{ memcpy(msg, &FIELD, sizeof(FIELD)); msg += sizeof(FIELD); }
P__FIELDLIST
// Return number of bytes in message.
return(msg - msg_);
}
void unpack(char *msg)
{
Fieldset fs;
memcpy(&fs, msg, sizof(fs));
msg += sizeof(fs);
#undef X
#define X(TYPE, FIELD)
if (fs[PP_CAT(Idx_, FIELD)])
{ memcpy(&FIELD, msg, sizeof(FIELD)); msg += sizeof(FIELD); }
P__FIELDLIST
}
};
An example of usage:
#define P__NAME My_class
#define P__FIELDLIST
X(int, i)
X(double, d)
X (int, j)
#include "xmitclass.hpp"
....
// Send only the int fields.
My_class::fieldset fs(false);
fs[Idx_i] = true;
fs[Idx_j] = true;
unsigned sz = my_inst.pack(fs, msg);
write(socket_fd, msg, sz);
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Thu Jun 16, 2005 8:13 am Post subject: Re: Calculating member offset at runtime |
|
|
Catalin Marinas wrote:
| Quote: |
You can use something like this where no structure needs to be
instantiated (same implementation in the Linux kernel):
#define offset_of(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
|
Well, sure, if you like undefined behavior and don't mind the
limitations that the original poster ascribed to offsetof. But why
bother? If those limitations are acceptable, use offsetof. Unlike this
version, it's portable.
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Kevin Lin Guest
|
Posted: Sat Jun 18, 2005 9:31 am Post subject: Re: Calculating member offset at runtime |
|
|
Pete Becker wrote:
| Quote: | Catalin Marinas wrote:
You can use something like this where no structure needs to be
instantiated (same implementation in the Linux kernel):
#define offset_of(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
Well, sure, if you like undefined behavior and don't mind the
limitations that the original poster ascribed to offsetof. But why
bother? If those limitations are acceptable, use offsetof. Unlike this
version, it's portable.
|
Yes. Perhaps I should have phrased my question better.
I don't really need a compile-time constant. Having dummy runtime
instantiations are fine. I just want to make sure that I can take a
runtime offset to a member no matter what the inheritance chain looks
like (i.e. tricky chains like virtual inheritance shouldn't give me an
incorrect offset).
Since I don't deal with low-level details very often, I was worried
that pointer calculations across different points of an inheritance
hierarchy may give me invalid results, but so far it seems my worries
were unfounded.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|