PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : verrückte funktion



TheDodger
18-05-2001, 19:11
ich habe ein etwas verzwicktes problem, wo ich nicht so sehr weiter weiß. das dumme dabie ist, das sich das problem auch reichlich schlecht beschreiben lässt, aber ich will es trotzdem mal versuchen. :-)

die vorraussetzung: ich programmiere derzeit eine eigne lib in c++, stelle aber das interface zur lib für c zur verfügung.

für folgenden funktionsaufruf soll die funktion abgebildet werden:
(der code ist _nicht_ vollständig!!!)

enum
{
NAME = 5,
FOO,
BAR,
SEMMEL,
NIX,
NOCH,
EIN,
BEISPIEL
};

char *name;
char *foo;
char *bar;
int nix;

func( NAME, name,
FOO , foo,
BAR , bar,
NIX , nix,
NULL );

printf("%s - %s - %s - %u\n", name, foo, bar, nix );

die vars, die mit enum vergeben werden sind nur bezeichner, um sie in eben etwas auseinander halten zu können.

ich möchte eben eine funktion haben, die ich einmal aufrufen und mehrere werte gleichzeitig zurückbekomme.
Oben soll nur als beispiel dienen, ich hätte auch das hier nehmen können:

func( BAR , bar,
NIX , nix,
NULL );

bislang habe ich das _versucht_ auf diese art zu lösen:

void func( int code, ... )
{
char *_name, bar;
char *foo = "schlumpf";

va_list arg;
va_start( arg, code );

for( ; ; code = va_arg( arg, int ) )
{
switch( code )
{
case NAME:
_name = ( char * )malloc( strlen( foo ) + 1 ); // reserviere mem
strncpy( _name, foo, strlen( foo ) + 1 ); // zuweisung

// printf( "%s\n", _name ); // testausgabe

// und jetzt muß _name noch in den addressraum der orig. var kopiert werden ... NUR WIE??
(char *)arg[1] = _name; // !segfault!

break;

case FOO:
break;

case NULL:
va_end( arg );
return;
}
}
}

func() darf hier komplett mittels c++ abgebildet sein, nur der aufruf muß zwingend als c funktion realisierbar sein.

hat jemand mein problem verstanden? ;-)

ich glaube, langsam versteh ich das selber nicht mehr ...

Bodo

jgbauman
19-05-2001, 14:19
Hi, ich hab dein Problem zwar nicht verstanden, da du nur beschreibst was Du machst, aber nicht was schiefgeht, aber trotzdem ein Tip:

Wenn Du ihn C++ etwas programmierst, was spaeter von C benutzt werden soll, darfst Du das extern "C" nicht vergessen, also:

#ifdef __cplusplus
extern "C" {
endif
void func(bla, ...);
...
#ifdef __cplusplus
}
endif
statt nur

void func(bla, ...);

TheDodger
19-05-2001, 15:40
was schiefgeht, ist relativ einfach ...
ich den übergebenen variablen steht einfach nicht's drin.
ich weiß nicht, wie ich - ohne die variable direkt mit dem funktionsaufruf zu übergeben - in diese was speichern/übergeben kann

Bodo

jgbauman
19-05-2001, 23:22
Hab ich wohl etwas zu schnell gelesen ;-)
Du willst die Werte kriegen nicht setzen, aha.

C hat eine "call by value" Semantik und da es die Referenzen aus C++ nicht kennt muss Du wohl mit Pointern arbeiten um "call by reference" zu kriegen.

Will ja jetzt nicht boese klingen, aber wenn Dir das entgangen sein sollte, dann besorg Dir erstmal ein Buch zu C/C++ ;-)


#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>

enum {
NAME = 5,
NIX
};

void func( int code, ... ) {
char *_name;
char *foo = "schlumpf";

int end;
va_list ap;
va_start( ap, code );

for( end = 0; !end ; code = va_arg( ap, int ) ) {
switch( code ) {
case NAME:
_name = ( char * )malloc( strlen( foo ) + 1 );
/* DONT USE THIS: strncpy( _name, foo, strlen( foo ) + 1 ); */
/* false security:
strncpy( ..., foo, strlen( foo) +1 )
is nothing else than
strcpy( ..., foo);
*/
strcpy( _name, foo);
/* va_arg must be used here, too */
*(va_arg(ap, char**)) = _name;
break;
case NIX:
/* va_arg must be used here, too */
*(va_arg(ap, int*)) = 42;
break;
case NULL:
end = 1;
break;
default:
/* FIXME error handling */
}
}
va_end( ap );
}

int main(){
char *name;
int nix;

/* call with address of variable instead of value.
If we dereference this address as a pointer inside of func()
we will be able to change the value
*/
func( NAME, &name,
NIX , &nix,
NULL );

printf("%s - %u\n", name, nix );

/* don´t forget to free allocated memory */
free(name);
}

[ 19. Mai 2001: Beitrag editiert von: jgbauman ]

TheDodger
21-05-2001, 05:32
:)
Stimmt, den das setzen habe ich ja schon gerafft :)
aber diesmal bin ich wohl an der zeigeraritmetik gescheitert ... und zwar massiv! :(

Doch dnake für deine hilfe!!!

Bodo