uFFI Structure Problem

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

uFFI Structure Problem

Georg Hagn
I have to implemet following external structure (extrakt from the
german api Doku):

typedef struct {
     /**@brief MUST be always 2. */
     uint32_t version;

     /** @brief Pointer to KeyStore -- Verweis auf den KeyStore, see
EricGetHandleToCertificate(). */
     EricZertifikatHandle zertifikatHandle;

     /** @brief PIN für den KeyStore.*/
     const char *pin;

     /**
      * @brief MUST be NULL in my context
               Dieser muss ...
               In allen anderen Fällen muss hier NULL übergeben
werden. Der Parameter abrufCode
               besteht aus 2 x 5 Zeichen, die mit "-" verbunden sind.
               Beispiel: "K6FG5-RS32P"
      */
     const char *abrufCode;

 } eric_verschluesselungs_parameter_t;

My Problem is, that i have to assign a NULL - value to the attribute abrufCode.
I have tried varies possibilities but I get always the error, that the
attribute abrufCode must have the value NULL.

" Extract from log-file:
019-09-05 17:08:52,257709[0x00007fe036a2f050] ERROR: Für die
übermittelte Datenart ist die Angabe eines Abrufcodes nicht zulässig,
daher muss für den Abrufcode der Wert NULL übergeben werden.
610001029"

How do I assign a NULL value to an attribute in a FFIExternalStructure?

Following my last attempt (extracted from the Pharo Booklet Colletion
"Calling Foreign Functions with Pharo May 31,2018")
I assign values not directly with the generated attributes but with
"api???" attributes.

FFIExternalStructure subclass: #ERiCVerschluesselungsParameter
    instanceVariableNames: ''
    classVariableNames: 'OFFSET_ABRUFCODE OFFSET_PIN OFFSET_VERSION
OFFSET_ZERTIFIKATHANDLE'
    package: 'Bajoras-ERiC'!


ERiCVerschluesselungsParameter class >> fieldsDesc [

    "ERiCVerschluesselungsParameter rebuildFieldAccessors"

    ^ #(
        uint32 version;
        ERiCZertifikatHandle * zertifikatHandle;
        char * pin;
        char * abrufCode;
    )
]

ERiCVerschluesselungsParameter >> initialize [

    self
        apiVersion: 2;
        apiAbrufCode: nil;
        apiPin: 'mySecret'.
]

ERiCVerschluesselungsParameter >> accessorMethods for: pin, version,
abrufCode, zertifikatHandle ("This method were automatically
generated")

ERiCVerschluesselungsParameter >> apiAbrufCode: aCode [

    | codeSize anAbrufCode |

    codeSize := 11.
    anAbrufCode := FFIExternalArray externalNewType: 'char' size: codeSize.
    1 to: codeSize do: [ :idx | anAbrufCode at: idx put: Character null ] .

    aCode ifNotNil: [
        aCode doWithIndex: [ :char :i | anAbrufCode at: i put: char ].
    ].

    self abrufCode: anAbrufCode.

]

ERiCVerschluesselungsParameter >> apiPin: aPin [

    | newPin |

    newPin := FFIExternalArray externalNewType: 'char' size: aPin size.
    aPin doWithIndex: [ :char :i | newPin at: i put: char ].

    self pin: newPin.
]


ERiCVerschluesselungsParameter >> apiVersion: aVersion [

    | cryptoVersion |

    cryptoVersion := 2.
    self version: cryptoVersion.

]

Thanks,
Georg Hagn

Reply | Threaded
Open this post in threaded view
|

Re: uFFI Structure Problem

EstebanLM


On 5 Sep 2019, at 17:41, Georg Hagn <[hidden email]> wrote:

I have to implemet following external structure (extrakt from the
german api Doku):

typedef struct {
    /**@brief MUST be always 2. */
    uint32_t version;

    /** @brief Pointer to KeyStore -- Verweis auf den KeyStore, see
EricGetHandleToCertificate(). */
    EricZertifikatHandle zertifikatHandle;

    /** @brief PIN für den KeyStore.*/
    const char *pin;

    /**
     * @brief MUST be NULL in my context
              Dieser muss ...
              In allen anderen Fällen muss hier NULL übergeben
werden. Der Parameter abrufCode
              besteht aus 2 x 5 Zeichen, die mit "-" verbunden sind.
              Beispiel: "K6FG5-RS32P"
     */
    const char *abrufCode;

} eric_verschluesselungs_parameter_t;

My Problem is, that i have to assign a NULL - value to the attribute abrufCode.
I have tried varies possibilities but I get always the error, that the
attribute abrufCode must have the value NULL.

" Extract from log-file:
019-09-05 17:08:52,257709[0x00007fe036a2f050] ERROR: Für die
übermittelte Datenart ist die Angabe eines Abrufcodes nicht zulässig,
daher muss für den Abrufcode der Wert NULL übergeben werden.
610001029"

How do I assign a NULL value to an attribute in a FFIExternalStructure?

The problem is not that is an structure but that is a char *, which is converted to a String in Pharo. 
Ideally, a nil should be mapped to NULL in this cases, but this is not working (never implemented).

Easiest workaround, just map abrufCode to void * instead char * (pointers are always same size). 

So you can have: 

myStryct abrufCode: ExternalAddress null. 
 
But of course, that will change the way you put the value there when *it is not* a NULL: 

myStryct abrufCode: ‘hello’ utf8Encoded copyWith 0.

(The copyWith: 0 is to ensure the void * will receive something with proper \0 finalisation)

Esteban


Following my last attempt (extracted from the Pharo Booklet Colletion
"Calling Foreign Functions with Pharo May 31,2018")
I assign values not directly with the generated attributes but with
"api???" attributes.

FFIExternalStructure subclass: #ERiCVerschluesselungsParameter
   instanceVariableNames: ''
   classVariableNames: 'OFFSET_ABRUFCODE OFFSET_PIN OFFSET_VERSION
OFFSET_ZERTIFIKATHANDLE'
   package: 'Bajoras-ERiC'!


ERiCVerschluesselungsParameter class >> fieldsDesc [

   "ERiCVerschluesselungsParameter rebuildFieldAccessors"

   ^ #(
       uint32 version;
       ERiCZertifikatHandle * zertifikatHandle;
       char * pin;
       char * abrufCode;
   )
]

ERiCVerschluesselungsParameter >> initialize [

   self
       apiVersion: 2;
       apiAbrufCode: nil;
       apiPin: 'mySecret'.
]

ERiCVerschluesselungsParameter >> accessorMethods for: pin, version,
abrufCode, zertifikatHandle ("This method were automatically
generated")

ERiCVerschluesselungsParameter >> apiAbrufCode: aCode [

   | codeSize anAbrufCode |

   codeSize := 11.
   anAbrufCode := FFIExternalArray externalNewType: 'char' size: codeSize.
   1 to: codeSize do: [ :idx | anAbrufCode at: idx put: Character null ] .

   aCode ifNotNil: [
       aCode doWithIndex: [ :char :i | anAbrufCode at: i put: char ].
   ].

   self abrufCode: anAbrufCode.

]

ERiCVerschluesselungsParameter >> apiPin: aPin [

   | newPin |

   newPin := FFIExternalArray externalNewType: 'char' size: aPin size.
   aPin doWithIndex: [ :char :i | newPin at: i put: char ].

   self pin: newPin.
]


ERiCVerschluesselungsParameter >> apiVersion: aVersion [

   | cryptoVersion |

   cryptoVersion := 2.
   self version: cryptoVersion.

]

Thanks,
Georg Hagn


Reply | Threaded
Open this post in threaded view
|

Re: uFFI Structure Problem

Georg Hagn
Thank you Esteban for your fast answer.

1) NULL Pointer assignment:
I have implemented your advise, and changed the attribute "abrufCode"
to "ExternalAddress null";
    >> fieldDesc #(myStruct uint32 version;  ...  void * abrufCode; )
The Structure has a NULL pointer assigned!? (see Inspector on MyStruct
"MyStruct (
version: 2
zertifikatHandle: (void*)@ 16r7F8400000001
pin: (char*)@ 16r7F84FB7FE5A0
abrufCode: (void*)@ 16r00000000
)"

But the problem is the same. I get the error: "attribute abrufCode
must have the value NULL." Any ideas?

2) coercing problem:
In my various tries I changed the whole structure to ExternalAddress
null. (In some circumstances I have to set the whole Structure to
NULL)
Now I got an coercing error. I think, because ExternalAddress is not a
FFIExternalStructure.
"
^ self ffiCall: #(int BearbeiteVorgang(String daten, String version,
int flags,  ExternalAddress * druck, MyStruct * crypto, TransferHandle
* transfer, RueckgabeHandle * rueckgabe, RueckgabeHandle *
serverantwort)).
"
Is it possible, NOT to decide between (here 4: druck and crypto can be
either Structures or NULL) ffi-calls?

Thank you, Georg








Am Do., 5. Sept. 2019 um 16:30 Uhr schrieb Esteban Lorenzano
<[hidden email]>:

>
>
>
> On 5 Sep 2019, at 17:41, Georg Hagn <[hidden email]> wrote:
>
> I have to implemet following external structure (extrakt from the
> german api Doku):
>
> typedef struct {
>     /**@brief MUST be always 2. */
>     uint32_t version;
>
>     /** @brief Pointer to KeyStore -- Verweis auf den KeyStore, see
> EricGetHandleToCertificate(). */
>     EricZertifikatHandle zertifikatHandle;
>
>     /** @brief PIN für den KeyStore.*/
>     const char *pin;
>
>     /**
>      * @brief MUST be NULL in my context
>               Dieser muss ...
>               In allen anderen Fällen muss hier NULL übergeben
> werden. Der Parameter abrufCode
>               besteht aus 2 x 5 Zeichen, die mit "-" verbunden sind.
>               Beispiel: "K6FG5-RS32P"
>      */
>     const char *abrufCode;
>
> } eric_verschluesselungs_parameter_t;
>
> My Problem is, that i have to assign a NULL - value to the attribute abrufCode.
> I have tried varies possibilities but I get always the error, that the
> attribute abrufCode must have the value NULL.
>
> " Extract from log-file:
> 019-09-05 17:08:52,257709[0x00007fe036a2f050] ERROR: Für die
> übermittelte Datenart ist die Angabe eines Abrufcodes nicht zulässig,
> daher muss für den Abrufcode der Wert NULL übergeben werden.
> 610001029"
>
> How do I assign a NULL value to an attribute in a FFIExternalStructure?
>
>
> The problem is not that is an structure but that is a char *, which is converted to a String in Pharo.
> Ideally, a nil should be mapped to NULL in this cases, but this is not working (never implemented).
>
> Easiest workaround, just map abrufCode to void * instead char * (pointers are always same size).
>
> So you can have:
>
> myStryct abrufCode: ExternalAddress null.
>
> But of course, that will change the way you put the value there when *it is not* a NULL:
>
> myStryct abrufCode: ‘hello’ utf8Encoded copyWith 0.
>
> (The copyWith: 0 is to ensure the void * will receive something with proper \0 finalisation)
>
> Esteban
>
>
> Following my last attempt (extracted from the Pharo Booklet Colletion
> "Calling Foreign Functions with Pharo May 31,2018")
> I assign values not directly with the generated attributes but with
> "api???" attributes.
>
> FFIExternalStructure subclass: #ERiCVerschluesselungsParameter
>    instanceVariableNames: ''
>    classVariableNames: 'OFFSET_ABRUFCODE OFFSET_PIN OFFSET_VERSION
> OFFSET_ZERTIFIKATHANDLE'
>    package: 'Bajoras-ERiC'!
>
>
> ERiCVerschluesselungsParameter class >> fieldsDesc [
>
>    "ERiCVerschluesselungsParameter rebuildFieldAccessors"
>
>    ^ #(
>        uint32 version;
>        ERiCZertifikatHandle * zertifikatHandle;
>        char * pin;
>        char * abrufCode;
>    )
> ]
>
> ERiCVerschluesselungsParameter >> initialize [
>
>    self
>        apiVersion: 2;
>        apiAbrufCode: nil;
>        apiPin: 'mySecret'.
> ]
>
> ERiCVerschluesselungsParameter >> accessorMethods for: pin, version,
> abrufCode, zertifikatHandle ("This method were automatically
> generated")
>
> ERiCVerschluesselungsParameter >> apiAbrufCode: aCode [
>
>    | codeSize anAbrufCode |
>
>    codeSize := 11.
>    anAbrufCode := FFIExternalArray externalNewType: 'char' size: codeSize.
>    1 to: codeSize do: [ :idx | anAbrufCode at: idx put: Character null ] .
>
>    aCode ifNotNil: [
>        aCode doWithIndex: [ :char :i | anAbrufCode at: i put: char ].
>    ].
>
>    self abrufCode: anAbrufCode.
>
> ]
>
> ERiCVerschluesselungsParameter >> apiPin: aPin [
>
>    | newPin |
>
>    newPin := FFIExternalArray externalNewType: 'char' size: aPin size.
>    aPin doWithIndex: [ :char :i | newPin at: i put: char ].
>
>    self pin: newPin.
> ]
>
>
> ERiCVerschluesselungsParameter >> apiVersion: aVersion [
>
>    | cryptoVersion |
>
>    cryptoVersion := 2.
>    self version: cryptoVersion.
>
> ]
>
> Thanks,
> Georg Hagn
>
>