Solved

Passing arrays of structures of arbitrary size ..

Posted on 1998-07-15
14
313 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
 
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
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
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

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
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.

707 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now