making a generic function wrapper

Discussion in 'C++' started by markww, Aug 15, 2006.

  1. markww

    markww Guest

    Hi,

    I have a wrapper around some 3rd party database library function. The
    pseudo code looks like the following - it is meant to open a table in a
    database, extract values from a table, then copy it into my own user
    defined structures. Since the process of opening and retrieving data
    from the database is exactly the same for all struct types, and the
    only part that's different is how the data is copied into the diff
    structs, I was wondering if there was a way I could have one generic
    wrapper, then somehow pass a callback or something to handle the
    copying over specific stuff: This is what I have now, an entire wrapper
    which reproduces the entire open table and copy to struct code for
    every different type of structure I have:


    bool MyDatabaseWrapper(structure A,
    structure B,
    structure N)
    {
    // Generic open stuff
    // Generic open stuff
    // Generic open stuff

    while (...) {

    // Generic execute stuff
    // Generic execute stuff

    // Now data is copied from the retrieved record into
    // my specific passed structure.
    if (struct type A) {
    a.income = data.col(0);
    }
    else if (struct type B) {
    b.name = data.col(0);
    b.age = data.col(1);
    }
    // and so on for many different struct types.
    }

    return true;
    }


    See I would rather have it like:

    bool MyGenericDatabaseWrapper(void **structType, CopyFunctionPtr)
    {
    // Generic open stuff

    while (...) {

    // Generic execute stuff

    // Ok now call the function pointer to handle copying the
    specifics
    // into the unknown struct type.
    CopyFunctionPtr(structType, data);
    }
    return true;
    }

    void CopyFunctionPtrStructA(struct &A, &data)
    {
    A.income = data.col(0);
    }

    void CopyFunctionPtrStructB(struct &B, &data)
    {
    B.name = data.col(0);
    B.age = data.col(1);
    }

    Ok I hope that was clear. This whole wrapper thing is to make sure this
    database lib I'm using is thread safe, and in the function there are
    like 30 lines of code that I don't want to recopy for every type of
    struct retrieval I have to do from the database.

    Thanks,
    Mark
     
    markww, Aug 15, 2006
    #1
    1. Advertising

  2. markww

    mlimber Guest

    markww wrote:
    > Hi,
    >
    > I have a wrapper around some 3rd party database library function. The
    > pseudo code looks like the following - it is meant to open a table in a
    > database, extract values from a table, then copy it into my own user
    > defined structures. Since the process of opening and retrieving data
    > from the database is exactly the same for all struct types, and the
    > only part that's different is how the data is copied into the diff
    > structs, I was wondering if there was a way I could have one generic
    > wrapper, then somehow pass a callback or something to handle the
    > copying over specific stuff: This is what I have now, an entire wrapper
    > which reproduces the entire open table and copy to struct code for
    > every different type of structure I have:
    >
    >
    > bool MyDatabaseWrapper(structure A,
    > structure B,
    > structure N)
    > {
    > // Generic open stuff
    > // Generic open stuff
    > // Generic open stuff
    >
    > while (...) {
    >
    > // Generic execute stuff
    > // Generic execute stuff
    >
    > // Now data is copied from the retrieved record into
    > // my specific passed structure.
    > if (struct type A) {
    > a.income = data.col(0);
    > }
    > else if (struct type B) {
    > b.name = data.col(0);
    > b.age = data.col(1);
    > }
    > // and so on for many different struct types.
    > }
    >
    > return true;
    > }
    >
    >
    > See I would rather have it like:
    >
    > bool MyGenericDatabaseWrapper(void **structType, CopyFunctionPtr)
    > {
    > // Generic open stuff
    >
    > while (...) {
    >
    > // Generic execute stuff
    >
    > // Ok now call the function pointer to handle copying the
    > specifics
    > // into the unknown struct type.
    > CopyFunctionPtr(structType, data);
    > }
    > return true;
    > }
    >
    > void CopyFunctionPtrStructA(struct &A, &data)
    > {
    > A.income = data.col(0);
    > }
    >
    > void CopyFunctionPtrStructB(struct &B, &data)
    > {
    > B.name = data.col(0);
    > B.age = data.col(1);
    > }
    >
    > Ok I hope that was clear. This whole wrapper thing is to make sure this
    > database lib I'm using is thread safe, and in the function there are
    > like 30 lines of code that I don't want to recopy for every type of
    > struct retrieval I have to do from the database.


    You might be able to do something like the second one, but you'll still
    have to have logic to determine what type to copy somewhere. In your
    second pseudo-code snippet above, that logic disappeared altogether,
    which makes me wonder if you had enough information to select the copy
    function outside the database wrapper function. If so, then you could
    use templates to come up with a solution, and if the different types
    have a common base class, you might consider using an object factory
    (see chapter 8 of _Modern C++ Design_ by Alexandrescu; download the
    accompanying library from http://sourceforge.net/projects/loki-lib).

    Cheers! --M
     
    mlimber, Aug 15, 2006
    #2
    1. Advertising

  3. markww

    markww Guest

    Hi mlimber,

    Thanks for replying. I think my example is overly complicated and I may
    have explained it incorrectly. Here's a much clearer example of what
    I'm trying to do - I'm really new with function pointers and the like,
    but if you have any suggestions with the following example that'd be
    great. In the meantime I'll do the reading you suggested,

    Thanks


    struct TYPE_A {
    string name, incoming;
    };
    struct TYPE_B {
    int age;
    };

    int main()
    {
    TYPE_A a;
    TYPE_B b;

    ReadData(CopyStructA, a);

    ReadData(CopyStructB, b);

    return 0;
    }

    void ReadData(void *pStruct, void *fnPtr)
    {
    // Read the data into 'data'.
    fnPtr(data, pStruct);
    }

    void CopyStructA(data, TYPE_A *a)
    {
    a.name = data.col(0);
    a.incoming = data.col(1);
    }

    void CopyStructB(data, TYPE_B *b)
    {
    b.age = data.col(0);
    }







    mlimber wrote:
    > markww wrote:
    > > Hi,
    > >
    > > I have a wrapper around some 3rd party database library function. The
    > > pseudo code looks like the following - it is meant to open a table in a
    > > database, extract values from a table, then copy it into my own user
    > > defined structures. Since the process of opening and retrieving data
    > > from the database is exactly the same for all struct types, and the
    > > only part that's different is how the data is copied into the diff
    > > structs, I was wondering if there was a way I could have one generic
    > > wrapper, then somehow pass a callback or something to handle the
    > > copying over specific stuff: This is what I have now, an entire wrapper
    > > which reproduces the entire open table and copy to struct code for
    > > every different type of structure I have:
    > >
    > >
    > > bool MyDatabaseWrapper(structure A,
    > > structure B,
    > > structure N)
    > > {
    > > // Generic open stuff
    > > // Generic open stuff
    > > // Generic open stuff
    > >
    > > while (...) {
    > >
    > > // Generic execute stuff
    > > // Generic execute stuff
    > >
    > > // Now data is copied from the retrieved record into
    > > // my specific passed structure.
    > > if (struct type A) {
    > > a.income = data.col(0);
    > > }
    > > else if (struct type B) {
    > > b.name = data.col(0);
    > > b.age = data.col(1);
    > > }
    > > // and so on for many different struct types.
    > > }
    > >
    > > return true;
    > > }
    > >
    > >
    > > See I would rather have it like:
    > >
    > > bool MyGenericDatabaseWrapper(void **structType, CopyFunctionPtr)
    > > {
    > > // Generic open stuff
    > >
    > > while (...) {
    > >
    > > // Generic execute stuff
    > >
    > > // Ok now call the function pointer to handle copying the
    > > specifics
    > > // into the unknown struct type.
    > > CopyFunctionPtr(structType, data);
    > > }
    > > return true;
    > > }
    > >
    > > void CopyFunctionPtrStructA(struct &A, &data)
    > > {
    > > A.income = data.col(0);
    > > }
    > >
    > > void CopyFunctionPtrStructB(struct &B, &data)
    > > {
    > > B.name = data.col(0);
    > > B.age = data.col(1);
    > > }
    > >
    > > Ok I hope that was clear. This whole wrapper thing is to make sure this
    > > database lib I'm using is thread safe, and in the function there are
    > > like 30 lines of code that I don't want to recopy for every type of
    > > struct retrieval I have to do from the database.

    >
    > You might be able to do something like the second one, but you'll still
    > have to have logic to determine what type to copy somewhere. In your
    > second pseudo-code snippet above, that logic disappeared altogether,
    > which makes me wonder if you had enough information to select the copy
    > function outside the database wrapper function. If so, then you could
    > use templates to come up with a solution, and if the different types
    > have a common base class, you might consider using an object factory
    > (see chapter 8 of _Modern C++ Design_ by Alexandrescu; download the
    > accompanying library from http://sourceforge.net/projects/loki-lib).
    >
    > Cheers! --M
     
    markww, Aug 15, 2006
    #3
  4. markww

    mlimber Guest

    markww wrote:
    > Hi mlimber,


    Hi. Please don't top-post here. Put your reply inline or below the post
    you are responding to.

    > Thanks for replying. I think my example is overly complicated and I may
    > have explained it incorrectly. Here's a much clearer example of what
    > I'm trying to do - I'm really new with function pointers and the like,
    > but if you have any suggestions with the following example that'd be
    > great. In the meantime I'll do the reading you suggested,
    >
    > Thanks
    >
    >
    > struct TYPE_A {
    > string name, incoming;
    > };


    N.B., this is not a POD struct (see
    http://www.parashift.com/c -faq-lite/intrinsic-types.html#faq-26.7).
    Referring to it with a void pointer is not recommended.

    > struct TYPE_B {
    > int age;
    > };
    >
    > int main()
    > {
    > TYPE_A a;
    > TYPE_B b;
    >
    > ReadData(CopyStructA, a);
    >
    > ReadData(CopyStructB, b);


    I think you meant:

    ReadData( &a, CopyStructA );
    ReadData( &b, CopyStructB );

    You'll also need CopyStructA and CopyStructB defined or have a
    prototype above.

    >
    > return 0;
    > }
    >
    > void ReadData(void *pStruct, void *fnPtr)


    I think you meant something like:

    void ReadData(void *pStruct, void (*fnPtr)(const Data&, void*) )

    > {
    > // Read the data into 'data'.
    > fnPtr(data, pStruct);
    > }


    Void pointers are generally discouraged in C++ since it throws away
    type information. Use templates instead:

    template<class T, class FN>
    void ReadData( T& t, FN fn )
    {
    const Data data = /* get data somehow */;

    // Convert data into the given struct
    fn( data, t );
    }

    >
    > void CopyStructA( data, TYPE_A *a)
    > {
    > a.name = data.col(0);
    > a.incoming = data.col(1);
    > }
    >
    > void CopyStructB(data, TYPE_B *b)
    > {
    > b.age = data.col(0);
    > }


    What type is data? A POD struct? An object? What is the return type of
    data.col()?

    You might consider writing the data to a std::stringstream and then
    extracting it with your custom std::eek:stream extraction operators for
    each type.

    Try writing a minimal but *complete* example that demonstrates what you
    are trying to do. Then we can help you further. See
    http://parashift.com/c -faq-lite/how-to-post.html#faq-5.8 on how to
    post code here.

    Cheers! --M
     
    mlimber, Aug 15, 2006
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Murat Tasan
    Replies:
    1
    Views:
    8,076
    Chaitanya
    Feb 3, 2009
  2. Simon Elliott

    Making a class more generic [part 1]

    Simon Elliott, Oct 27, 2003, in forum: C++
    Replies:
    0
    Views:
    304
    Simon Elliott
    Oct 27, 2003
  3. Simon Elliott

    Making a class more generic [part 2]

    Simon Elliott, Oct 27, 2003, in forum: C++
    Replies:
    2
    Views:
    287
    Simon Elliott
    Oct 28, 2003
  4. Replies:
    2
    Views:
    448
  5. minlearn
    Replies:
    2
    Views:
    464
    red floyd
    Mar 13, 2009
Loading...

Share This Page