Solved

Passing arrays of structures of arbitrary size ..

Posted on 1998-07-15
14
315 Views
Last Modified: 2012-06-21
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
Comment
Question by:notanexpert
  • 6
  • 4
  • 3
  • +1
14 Comments
 
LVL 1

Author Comment

by:notanexpert
ID: 1251693
Edited text of question
0
 
LVL 11

Expert Comment

by:alexo
ID: 1251694
Consider:

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

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

0
 
LVL 1

Author Comment

by:notanexpert
ID: 1251695
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
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 
LVL 1

Author Comment

by:notanexpert
ID: 1251696
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
 
LVL 11

Expert Comment

by:alexo
ID: 1251697
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
 
LVL 4

Expert Comment

by:sganta
ID: 1251698
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
 
LVL 4

Expert Comment

by:sganta
ID: 1251699
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
 
LVL 4

Expert Comment

by:sganta
ID: 1251700
I am sorry, this could be
loginStr = (char *)malloc(30*sizeof(char));
    strcpy(loginStr,mine[0].u.s);
0
 
LVL 1

Author Comment

by:notanexpert
ID: 1251701
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
 
LVL 11

Accepted Solution

by:
alexo earned 150 total points
ID: 1251702
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
 
LVL 1

Author Comment

by:notanexpert
ID: 1251703
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
 
LVL 1

Author Comment

by:notanexpert
ID: 1251704
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
 
LVL 11

Expert Comment

by:alexo
ID: 1251705
>> 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
 

Expert Comment

by:effectivista
ID: 13475115
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

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Convert image to byte array 8 201
Read file descriptor 3 in C 14 107
Trouble linking program with -lcrypt 3 149
Please explain C language error codes ? 5 10
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
The goal of this video is to provide viewers with basic examples to understand how to use strings and some functions related to them in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.

778 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question