[C] DLL: welk union-veld is gevuld?

Pagina: 1
Acties:

  • scorpionv
  • Registratie: Juni 2000
  • Laatst online: 17-08 00:02

scorpionv

This space for rent

Topicstarter
Zoals de topic titel al aangeeft, ben ik aan het stoeien met DLL's in C. Dat gaat vrij aardig na het doorworstelen van wat tutorials en GoT :)

Maar nu kom ik een raar probleem tegen: ik heb een 3rd-party DLL, en als ik een functie uit die DLL gebruik schrijft de DLL-functie een waarde in een union. Deze union bestaat uit wel 20 velden, met allerlei data-typen, van floats tot char[].

Het staat niet vast welk veld/variabele er wordt gevuld, maar ik wil wél de data uit het gevulde veld gebruiken. Hoe kom ik er achter welk veld gevuld wordt door de DLL-functie?
Ik heb me al suf gezocht, maar ik kan er niet echt iets over vinden, normaal weet je bij het aanroepen van je functie welk veld je vol gaat schrijven, maar dat weet ik dus niet omdat ik die DLL niet heb gemaakt.

Wie weet het wel :?

Fun while it lasted: World Community Grid!


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Niet, een union is een union. Zonder bijbehorend type-field (zoals iedere Variant-implementatie die heeft) of andere kennis vooraf heb je er niets aan.

Professionele website nodig?


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 01:56
C union's zijn hele simpele datastructuren. Je kunt ze zien als structs waarbij alle velden op hetzelfde adres beginnen. Een union 'weet' verder niet welke velden 'gevuld' zijn; in het geheugen staat namelijk altijd wel iets! Je kunt dan ook altijd alle velden tegelijk gebruiken. Het is bijvoorbeeld niet ongebruikelijk om een integer op te splitsen in twee 16-bits words of vier 8-bits bytes, op zo'n manier:
C:
1
2
3
4
5
6
7
8
union {
  unsigned long int i;
  unsigned short int w1, w2;
  unsigned char b1, b2, b3, b4;
} data;

data.i = 123456;
printf("%i %i\n", data.w1, data.w2);

Ik wil hier mee illustreren dat een union dus geen verschillende datavelden heeft (zoals een struct) maar eigenlijk alleen maar verschillende manieren om bij dezelfde data te komen. Echter, het kan ook goed voorkomen dat de velden in een union niet bedoeld zijn om allemaal tegelijk gebruikt te worden. Als jouw union een heleboel velden kent is dat waarschijnlijk het geval. Je moet dan van de DLL een indicatie moeten krijgen welk veld je moet gebruiken. Zonder die indicatie is het namelijk onmogelijk om te "raden" welk veld het goede is, zoals nu hopelijk duidelijk is.

[ Voor 12% gewijzigd door Soultaker op 11-07-2003 14:03 ]


  • scorpionv
  • Registratie: Juni 2000
  • Laatst online: 17-08 00:02

scorpionv

This space for rent

Topicstarter
Hmmz, dat is niet zo best, maar wat heb ik dan aan m'n DLL :?

Even ter verduidelijking m'n union;

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
typedef union TVAR_BLOC
 {
        /* max. 3,75 kbyte VAR-DATA */
    float   fReal;               /*DEZ*/
    long    lInteger;            /*GANZ*/
        long    lBinary;             /*BINAER*/
        char    cChar;               /*ZEICHEN*/
        char    cText   [80];        /*TEXT*/
        float   fPoint  [MAX_AXIS];  /*PUNKT*/
        float   fJcPoint[MAX_AXIS];  /*MK_PUNKT*/
        float   fWcFrame[MAX_WC];    /*RK_RAHMEN*/

        /*Arrays*/
    float   AryReal     [ 960];
        long    AryInteger  [ 960];
        long    AryBinary   [ 960];
        char    AryChar     [3840];
        char    AryText     [3840];
        float   AryPoint    [ 960];
        float   AryJcPoint  [ 960];
        float   AryWcFrame  [ 960];
 }TVAR_BLOC;


Een verder niet gedefinieerde functie schrijft een waarde in deze union, kan ik die er echt niet met een trucje uitkrijgen?

Fun while it lasted: World Community Grid!


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Normale praktijk is om dit soort dingen in een encapsulating struct te zetten, als volgt:
C++:
1
2
3
4
5
typedef struct
  {
  TVAR_BLOC m_Variant;
  int m_Type;
  } t_Parameters;

Als je die type niet hebt kun je er niets mee... :/

Professionele website nodig?


  • scorpionv
  • Registratie: Juni 2000
  • Laatst online: 17-08 00:02

scorpionv

This space for rent

Topicstarter
Ik zit net te spieken in een voorbeeldprogje met die DLL (wat overigens niet werkt :(), maar daar gooit de DLL deze;

C:
1
2
long        VarSize;                 /*size of variable in bytes*/
long        ElementSize;             /*size of one element in bytes*/


waarden in een struct. Moet ik daar misschien mee uitvogelen hoe of wat :?

Fun while it lasted: World Community Grid!


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Post de signature van de functie eens en alle structuren/unions/typedefs die (in)direct als parameter voor die functie gebruikt worden.

Professionele website nodig?


  • scorpionv
  • Registratie: Juni 2000
  • Laatst online: 17-08 00:02

scorpionv

This space for rent

Topicstarter
curry684 schreef op 11 juli 2003 @ 14:07:
Normale praktijk is om dit soort dingen in een encapsulating struct te zetten, als volgt:
C++:
1
2
3
4
5
typedef struct
  {
  TVAR_BLOC m_Variant;
  int m_Type;
  } t_Parameters;

Als je die type niet hebt kun je er niets mee... :/
Dit volg ik niet helemaal, je declareert hier een struct met een int erin. Kan een functie die een char terug geeft deze toch gebruiken?

Fun while it lasted: World Community Grid!


  • scorpionv
  • Registratie: Juni 2000
  • Laatst online: 17-08 00:02

scorpionv

This space for rent

Topicstarter
OK, hou je vast:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#define _MAX_STRING           255
#define MAX_DIR               256
#define MAX_LEVEL               4     /* Anzahl der Eingabeebenen */
#define MAX_DIMENSION          10     /* Max. Felddimensionen */

typedef union TVAR_BLOC
 {
        /* max. 3,75 kbyte BAPS-VAR-DATA */
    float   fReal;               /*DEZ*/
    long    lInteger;            /*GANZ*/
        long    lBinary;             /*BINAER*/
        char    cChar;               /*ZEICHEN*/
        char    cText   [80];        /*TEXT*/
        float   fPoint  [MAX_AXIS];  /*PUNKT*/
        float   fJcPoint[MAX_AXIS];  /*MK_PUNKT*/
        float   fWcFrame[MAX_WC];    /*RK_RAHMEN*/

        /*Arrays*/
    float   AryReal     [ 960];
        long    AryInteger  [ 960];
        long    AryBinary   [ 960];
        char    AryChar     [3840];
        char    AryText     [3840];
        float   AryPoint    [ 960];
        float   AryJcPoint  [ 960];
        float   AryWcFrame  [ 960];
 }TVAR_BLOC;

typedef struct TVRdWrVar
{
    /*i*/
    long        ChannelId;
    char        szPath   [MAX_DIR];      /* "c:\\path\\filename" */
    char        szProcess[12];           /* for further use: Process selection*/
    char        szVarName[_MAX_STRING];  /* VarName e.g.: "p1.x_k" */
    long        bCommonID;               /*0: no CID-check,   1: CID-check active*/
    long        bPCRC;                   /*0: read var in RC, 1: read var in PC  */
    long        WrNumber;                /*write WrNumber elements(components) of variable*/
                                         /*write the complete variable if WrNumber = -1   */
                                         /*WrNumber is not used in read function          */
    long        AddressMode;             /*0: input VarName,  1: input RelAddress*/

    /*i/o:  AddressMode=0 == output,  AddressMode=1 == input*/
    TFIL_NAM_RHO FileNameRho;            /*only for internal use*/
    long        Level;                   /*0:variable in PKT-file,  1:variable in IRD-file*/
    long        RelAddress;              /*relative address of variable*/
    long        VarSize;                 /*size of variable in bytes*/
    long        ElementSize;             /*size of one element in bytes*/
    long        CommonId;
    long        lReserved[128];          /*reserved for further use */

    TVAR_BLOC   Var;                     /*BAPS-VAR-DATA-BLOC*/

} TVRdWrVar;

Fun while it lasted: World Community Grid!


  • scorpionv
  • Registratie: Juni 2000
  • Laatst online: 17-08 00:02

scorpionv

This space for rent

Topicstarter
En dit is de functie-call uit de header-file:
C:
1
EXTERN long STDCALL rVReadVar( TVReadVar *PVReadVar );


En die wordt zo gebruikt in het voorbeeldprogramma:
C:
1
2
3
4
5
6
7
8
9
lRet = rVReadVar( &PVReadVar );
    
    /* show result              */
    if (lRet==0) //Keine Fehler
    {
        nElements = PVReadVar.VarSize / PVReadVar.ElementSize;
        VarShow(&PVReadVar, nElements);
    }
    else ErrorHandler(lRet,CVReadVar);


Sorry voor de hoeveelheid tekst, maar ik wil niet onduidelijk zijn :)

Fun while it lasted: World Community Grid!


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Neuh ik had erom gevraagd, dus excuus voor de hoeveelheid niet nodig :)

Zoals het er naar uitziet zul je echt uit die overigen 15 members van de struct moeten zien te destilleren wat er in de union staat. Met docs is het wellicht handiger :D

Professionele website nodig?


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 01:56
Het commentaar achter de union velden doet vermoeden dat er misschien constanten als MK_PUNKT of ZEICHEN gedefinieerd zouden zijn, die als typeindicatie gebruikt worden. Kun je die constanten nog ergens terugvinden? Worden die misschien ergens in een van de struct members ingesteld (CommonId ofzo)? Retourneert je functie niet een typeindicatie?

  • scorpionv
  • Registratie: Juni 2000
  • Laatst online: 17-08 00:02

scorpionv

This space for rent

Topicstarter
@curry684; helaas heb ik geen docs, dat maakt het zo lekker transparant, und die Deutsche Techniker haben schon Ferien, dus ik zal het lekker zelf op moeten lossen.

@Soultaker; hier wordt in het programma iets gedaan voordat de functie VarShow wordt aangeroepen, misschien is dat de sleutel tot het juiste element:?
C:
1
2
3
4
5
if (lRet==0) //Keine Fehler 
    { 
        nElements = PVReadVar.VarSize / PVReadVar.ElementSize; 
        VarShow(&PVReadVar, nElements); 
    }

Ik zal volgende week iig de header-files nog eens goed doorspitten voor een aanwijzing, en als ik wat vind laat ik zeker wat weten :)

Waarschijnlijk kan ik volgende week wat testen doen, misschien dat dat wat oplevert. Ook hiervoor geldt, als ik het werkend krijg dan post ik de oplossing.

Iiig bedankt voor de input, en als jullie nog wat te binnen schiet; post het! :)

Fun while it lasted: World Community Grid!


  • scorpionv
  • Registratie: Juni 2000
  • Laatst online: 17-08 00:02

scorpionv

This space for rent

Topicstarter
Inmiddels heb ik een workaround voor m'n probleem gevonden, ik eis in m'n programma dat de gebruiker weet welk type data hij op wil halen (geheel getal, getal met komma, één letter, meerdere letters) 8)7

Zodra de gebruiker het datatype weet en ingeeft, weet ik in welk veld ik moet zoeken :)
Bedankt voor de feedback iedereen, en m'n excuses voor deze dirty oplossing :)

Fun while it lasted: World Community Grid!

Pagina: 1