• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 330
  • Last Modified:

Passing arrays of structures of arbitrary size ..

Alright. I've been given an API mess around with .. I'm using the GNU gcc compiler on a Solaris box. The API demands that I write what is eseentially a call-back function. Ie: I have to write the function to comply with this prototype:

void grabData(  int argc,
            struct LiveWireCCallData mine[],
            struct LiveWireCCallData *result,
            pblock* pb,
            Session* sn,
            Request* rq );

LiveWireCCallData is a struct declared in "libcm.h"

Here's the first bit of my source code ..

--------------------------------------[ libcm.c ]-----------
#define XP_UNIX
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/sockio.h>
#include </home/garrett/calendarApi/capi.h>
#include <stdlib.h>
#include <malloc.h>
#include "libcm.h"

int writeToFile
(
void * outFile,          /* The data pointer passed to SetStreamCallBacks */
char * inBuffer,         /* A character buffer of data to write */
int BufSize,             /* The size of the character buffer */
int * charsWritten);     /* read call backs only, return characters written */

static char * strAdd(char * oldStrPtr, char * addMe);

char * dataPtr = 0;
FILE * outFile = NULL;
CAPISession Se = NULL;
CAPIHandle handles[1] = { NULL };
CAPIStatus status = CAPI_ERR_OK;
CAPIStream myStream=NULL;
struct LiveWireCCallData mine[];
struct LiveWireCCallData *result;

char *loginStr;
char* handleStr;
char *password;
char *from;
char *to;

void grabData(  int argc,
            struct LiveWireCCallData mine[],
            struct LiveWireCCallData *result,
            pblock* pb,
            Session* sn,
            Request* rq )
{

loginStr = mine[0].u.s;

..... etc, etc ... the error happens here ... the error happens when I try to access anything from mine[]

---------------------------------------------------

The compilation error is

libcm.c:47: arithmetic on pointer to an incomplete type
libcm.c:47: dereferencing pointer to incomplete type

My compile command line is
gcc -fpic -G -o libcm.so jsaccall.so -lc libcapi.so -lsocket -lc2 libcm.c

but I think the issue really comes down to this:
It is my understanding that this other 'service' which will call this function in my shared object will pass an arbitrary sized array of LiveWireCCallData structs. What I need is a way to telling my shared object to instantiate an array of this arbitrary size when my grabData function is called. I cannot change the prototype of this function as it is a standardized interface. I suspect that the GNU compiler might just be a little more uptight about things like this than cc, but if anyone can point out
a) a dumb error in my code (maybe the order in which things are declared/defined?)
b) a solution .. ie: the 'right way'.

Anywho, if anyone needs more info on what's goin' on, I'd be glad to help. .. oh and here's the header file (not written by me .. this is what I have to comply to .. )

----------------[ header file "libcm.h ]---------------------

#ifndef _jsaccall_h_
#define _jsaccall_h_

#include "include/base/pblock.h"
#include "include/base/session.h"
#include "include/frame/req.h"
#include "include/frame/http.h"

#define LIVEWIRE_CCALLDATA_UNKNOWN 0
#define LIVEWIRE_CCALLDATA_NULL 1
#define LIVEWIRE_CCALLDATA_INTEGER 2
#define LIVEWIRE_CCALLDATA_DOUBLE 3
#define LIVEWIRE_CCALLDATA_STRING 4
#define LIVEWIRE_CCALLDATA_BOOLEAN 5

struct LivewireCCallData {
    int tag; /* from above LIVEWIRE_CCALLDATA_* */
    union {
        int i; /* integer or boolean */
        double d; /* double */
        char* s; /* string */
    } u;
    void (*freeString)(char*);
};

/*
 *
 * your function should conform to this
 *
 */
typedef void
(*LivewireUserCFunction)( int argc, struct LivewireCCallData argv[],
    struct LivewireCCallData* result, pblock* pb, Session* sn, Request* rq );

#endif /* _jsaccall_h_ */
0
notanexpert
Asked:
notanexpert
  • 6
  • 4
  • 3
  • +1
1 Solution
 
notanexpertAuthor Commented:
Edited text of question
0
 
alexoCommented:
Consider:

    /* Declare a pointer */
    struct LiveWireCCallData *mine;

    /* Allocate memory for n items */
    mine = calloc(number_of_items, sizeof(struct LiveWireCCallData));

0
 
notanexpertAuthor Commented:
I'd work on that kind of implementation if it wern't for the fact that the supplied example source code with the API doesn't use any mallocing at all. It just presumes that memory will be allocated for the passed structs when the data gets passed.

Are you 100% thats the only way of doing this? The sample code I'm talking about is distributed with a well known commercial product. I may be going out on a leap here, but I presume they compiled it at least once before it was shipped. ;)


0
Live webcast with Pinal Dave

Pinal Dave will teach you tricks to help identify the real root cause of database problems rather than red herrings. Attendees will learn scripts that they can use in their environment to immediately figure out their performance Blame Shifters and fix them quickly.

 
notanexpertAuthor Commented:
Incidentally, it looks more like a matter of scope and the fact that I have to define freeString .. the compiler calls the LiveWireCCallData an incomplete type it looks like, because freeString(char* s) isn't defined. But I can't figure out where to define it, and how to make sure scope issues are copesthetic.
0
 
alexoCommented:
when the compiler says "incomplete type" it means that you declared some structure/class without providing the implementation details.  While it is OK for pointers and stuff, you get into trouble if you try to access the data.

Example:

    struct Something; // Incomplete
    struct Something *p; // OK, just a pointer
    MyFunc(p); // Still OK
    p->x = 3; // Error.  How do I know 'x' is a member of struct Something?

However:

    struct Something { int x; }; // Complete
    struct Something *p; // OK, just a pointer
    MyFunc(p); // Still OK
    p->x = 3; // OK, 'x' is known


0
 
sgantaCommented:
Hi !
Why can't you try like this

strcpy(loginStr,mine[0].u.s);

If this does'nt work try this

loginStr = (char *)malloc(sizeof(char));
strcpy(loginStr,mine[0].u.s);

Best of Luck !
0
 
sgantaCommented:
Hi !
Why can't you try like this

strcpy(loginStr,mine[0].u.s);

If this does'nt work try this

loginStr = (char *)malloc(sizeof(char));
strcpy(loginStr,mine[0].u.s);

Best of Luck !
0
 
sgantaCommented:
I am sorry, this could be
loginStr = (char *)malloc(30*sizeof(char));
    strcpy(loginStr,mine[0].u.s);
0
 
notanexpertAuthor Commented:
sqanta .. the only reason I'm recting yar answer is because I can compile some code a coworker did with the exact same API without ever having to use malloc. I'd like to do it the way the API writers intended it to be used, so ... alexo, you're definately on the right track. So here is thr struct def:

struct LivewireCCallData {
         int tag; /* from above LIVEWIRE_CCALLDATA_* */
         union {
             int i; /* integer or boolean */
             double d; /* double */
             char* s; /* string */
         } u;
         void (*freeString)(char*);
     };

It's in the header file (jsaccall.h) .. so I think it's complaining cause I havn't actually defined freeString(char*) .. so I guess my question is, where do I have to put the definition of freeString(char*)?
0
 
alexoCommented:
I think you just have to include the header file so the compiler sees the structure definition when it comes to the "loginStr = mine[0].u.s;" line.

Add at the beginning of the file:
    #include <jsaccall.h> // or "jsaccall.h"

You'd probably also want to delete these lines:
    struct LiveWireCCallData mine[];
    struct LiveWireCCallData *result;

An "incomplete type" error is almoss always a result of missing #include's.
0
 
notanexpertAuthor Commented:
Actually, the only reason I feel a little better about this is cause none of ya noticed it either ... but I finally found it ... did anyone see the def in the header file?
LivewireCCallData ... and then in my code
LiveWireCCallData

Believe you me, I'm scarelet red from embarassement.

The case of the caps strikes again. I'm terribly embarrassed, but tho you didn't actually get the right answer Alexo, you did point me in the right direction, so here's 75 points for ya ..
0
 
notanexpertAuthor Commented:
Heehee, or ... take all 150 ;) Still figurin' out how this place works, I guess it makes sense that I can't lower the points to a question of course ... thanks alot, too!
0
 
alexoCommented:
>> Still figurin' out how this place works.

You assign a number of points to the question, they are removed from your account.
When you grade an answer, the answerer is awarded a number of "quality points" (of no use or value whatsoever) that equals the oferred points multiplied by the grade.

In this case you gave me 450 out of a possible 600 helping maintain my position in the top 20 for a little bit longer against the ruthless competition.  Thanx ;-)

The reason you cannot lower the number of points should be pretty obvious.  You are given the choice to remove the question if it does not have any pending or rejected answers.

To complicate things a bit, if a question does not get any activity in three weeks it is autograded (with a 'C' score) if there is a pending answer or removed (and the points refunded) if it is not.  Autograded answerss are the second most annoying thing to the experts.

Finally, the EE customer support staff handles any "unusual" situations such as requests to remove a question, refund or redistribute points, etc.

The interface is not perfect but we manage somehow...
0
 
effectivistaCommented:
i got a code like

#include        "unp.h"

int
main(int argc, char **argv)
{
        int                                     listenfd, connfd;
        pid_t                           childpid;
        void                            sig_chld(int), sig_int(int), web_child(int);
        socklen_t                       clilen, addrlen;
        struct sockaddr         *cliaddr;

        if (argc == 2)
                listenfd = Tcp_listen(NULL, argv[1], &addrlen);
        else if (argc == 3)
                listenfd = Tcp_listen(argv[1], argv[2], &addrlen);
        else
                err_quit("usage: serv01 [ <host> ] <port#>");
        cliaddr = Malloc(addrlen);

        Signal(SIGCHLD, sig_chld);
        Signal(SIGINT, sig_int);

        for ( ; ; ) {
                clilen = addrlen;
                if ( (connfd = accept(listenfd, cliaddr, &clilen)) < 0) {
                        if (errno == EINTR)
                                continue;               /* back to for() */
                        else
                                err_sys("accept error");
                }

                if ( (childpid = Fork()) == 0) {        /* child process */
                        Close(listenfd);        /* close listening socket */
                        web_child(connfd);      /* process request */
                        exit(0);
                }
                Close(connfd);                  /* parent closes connected socket */
        }
}
/* end serv01 */

/* include sigint */
void
sig_int(int signo)
{
        void    pr_cpu_time(void);

        pr_cpu_time();
        exit(0);
}
 and when coompiling i m getting some problem like '

 gcc -o ser1 serv01.c
In file included from /usr/include/netinet/in.h:23,
                 from unp.h:17,
                 from serv01.c:2:
/usr/include/stdint.h:49: conflicting types for `uint8_t'
/usr/include/bits/sockaddr.h:29: previous declaration of `uint8_t'
In file included from serv01.c:2:
unp.h:51:30: sys/filio.h: No such file or directory
unp.h:54:31: sys/sockio: No such file or directory
In file included from serv01.c:2:
unp.h:114: redefinition of `struct in_pktinfo'


how can i slve this problem
where the file sys/filio.h and sys/sockio are placed
pls help me from where i can get these files
 dhiraj
0

Featured Post

Turn Raw Data into a Real Career

There’s a growing demand for qualified analysts who can make sense of Big Data. With an MS in Data Analytics, you can become the data mining, management, mapping, and munging expert that today’s leading corporations desperately need.

  • 6
  • 4
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now