2015-12-18 15 views
6

Sono un programmatore COBOL e il mio ultimo progetto è quello di connettere un'applicazione COBOL a un database SQLite3.Come scrivere callback SQLite in COBOL

Ho seguito this guide e la loro soluzione è esattamente ciò di cui avrei bisogno nella mia applicazione COBOL. Sono riuscito a creare, connettere, inserire dati e chiudere il database, ma il problema sorge quando provo a selezionare i dati dal database.

Nel tutorial, utilizzano una richiamata con doppi puntatori.

static int callback(void *NotUsed, int argc, char **argv, char **azColName){ 
    int i; 
    for(i=0; i<argc; i++){ 
     printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL"); 
    } 
    printf("\n"); 
    return 0; 
} 

La mia soluzione in COBOL è la seguente

WORKING-STORAGE SECTION. 
    *----------------------------------------------------------------* 

    01 sqlite3-db   pointer. 
    01 err_msg   pointer. 
    01 sqlite    pointer. 
    01 res    pointer. 

    01 notused   pointer. 
    01 argc    pic 99 comp-5. 
    01 argv    pointer. 
    01 azColName   pointer. 
    01 Writefunction-Ptr procedure-pointer. 

    procedure division. 
      set Writefunction-Ptr to entry "sqlite-callback". 

      *>Random code. 

      call "sqlite3_exec" using 
      by value sqlite3-db 
      by reference sqlQuery 
      by value Writefunction-Ptr 
      by value 0 
      by reference err_msg 
      returning rc 
      end-call 

      *>Random code. 

    stop run. 

    entry "sqlite-callback" using 
      by value notused 
      by value argc 
      by reference argv 
      by reference azColName. 

     display argc 

     goback. 
    Entry-Termination. 

Il callback funziona perché si chiama il numero di righe che viene restituito dal database, e l'argc intero contiene il numero di colonne che le la tabella contiene.

Le domande sono:

puntatori

doppie in COBOL, come sono rappresentati? Nella mia soluzione dichiaro un puntatore e richiamo il callback con "per riferimento" sul puntatore. Non so se questo è il modo corretto per rappresentare i doppi puntatori in COBOL?

Come visualizzare il contenuto di azColName e argv e non solo l'indirizzo di memoria a cui punta il puntatore?

Ho cercato ora di utilizzare SET ADDRESS OF, ma non riesco ancora a farlo funzionare. Deve essere qualcosa che mi è sfuggito. La mia soluzione al momento appare come:

WORKING-STORAGE SECTION. 
01 argv pointer. 

Linkage Section. 
01 link-area pic x. 

procedure division using link-area. 

*> RANDOM CODE 

    set address of link-area to argv 
    call "sqlite3_exec" using 
     by value sqlite3-db 
     by reference z"SELECT * FROM Cars" 
     by value Writefunction-Ptr 
     by value 0 
     by reference err_msg 
     returning rc 
     end-call 

*> RANDOM CODE 


entry "sqlite-callback" using 
    by value notused 
    by value argc 
    by reference argv 
    by reference azColName. 

    display argc. 

    if address of link-area not = null 
    display "Contents of new argv: " link-area 
    else 
    display "empty" 
    end-if 

    goback. 

Entry-Termination. 

Il risultato che ottengo è che l'istruzione if è sempre false, quindi viene visualizzata la stringa "vuoto". Ma ancora argc è impostato sul numero di colonne nella tabella.

La soluzione di lavoro:

WORKING-STORAGE SECTION. 

    01 argv. 
     03 firstColumn pointer. 
     03 secondColumn pointer. 
     03 thirdColumn pointer. 

    01 azColName   pointer. 
    01 argc    pic 99 comp-5. 
    01 notused   pointer. 

    01 Writefunction-Ptr procedure-pointer. 

    *----------------------------------------------------------------- 
    Linkage Section. 

    01 Cars_Id  pic 9(2). 
    01 Cars_Name  pic X(20). 
    01 Cars_Price pic 9(10). 
    /----------------------------------------------------------------- 
    procedure division. 

    //code  

    set Writefunction-Ptr to entry "sqlite-callback". 

      initialize sqlQuery 
      move z"SELECT * FROM Cars;" to sqlQuery 


      call "sqlite3_exec" using 
      by value sqlite3-db 
      by reference sqlQuery 
      by value Writefunction-Ptr 
      by value 0 
      by reference err_msg 
      returning rc 
      end-call 

    //code 

    stop run. 



    entry "sqlite-callback" using 
      by value notused 
      by value argc 
      by reference argv 
      by reference azColName. 

     set address of Cars_Id to firstColumn 
     set address of Cars_Name to secondColumn 
     set address of Cars_Price to thirdColumn 


     display Cars_Id "|" Cars_Name "|" Cars_Price 

     goback. 
    Entry-Termination. 
+1

Quale COBOL stai utilizzando? Si compila senza una SEZIONE COLLEGAMENTO? Dai un'occhiata a SET ADDRESS OF x TO your-pointer, dove x è definito nella LINKAGE SECTION ed è la dimensione e il tipo che vuoi. Ciò consentirà quindi l'accesso ai dati indicati dal puntatore. –

+0

Marcus sta utilizzando un compilatore MicroExcenter ServerExpress. – Anders

risposta

3

Abbiamo davvero bisogno di conoscere il compilatore che si sta utilizzando.

La tua istruzione SET è nel posto sbagliato. argv ha un indirizzo solo quando viene chiamato lo ENTRY. Prima che la voce venga chiamata, sarà zero binario o spazzatura imprevedibile.

Se si sposta il SET dopo l'ENTRATA, sarà quindi possibile utilizzare il valore di LINK-AREA. argv sarà ancora solo un indirizzo, ma LINK-AREA (digli un nome migliore, per favore) indicherà quell'indirizzo, quindi definiscilo come dovrebbe essere argv, e quindi LINK-AREA può essere usato per ottenere il contenuto attuale di argv.


Quando si utilizza BY REFERENCE il compilatore genera codice per passare un puntatore con l'indirizzo il dato.

Sul numero PROCEDURE DIVISION USING o ENTRY USING l'elemento deve essere anche DA RIFERIMENTO e il compilatore genera il codice per mappare la definizione della SEZIONE COLLEGAMENTO all'indirizzo specificato.

Questo è simile se si utilizza BY CONTENT, ma il compilatore prende una copia dei dati all'interno del programma e passa un puntatore che fa riferimento a quello.Sull'USO della DIVISIONE PROCEDURA o ENTRATA che è ancora definita come DA RIFERIMENTO.

Con BY VALUE il compilatore "passa" il valore effettivo, sebbene esistano dei limiti, sia quelli specificati nello Standard che le estensioni dello standard con il compilatore corrente. L'UTILIZZO della PROCEDURA DIVISION o ENTRY dovrebbe specificare anche PER VALORE.

Su tutti gli USING, PER RIFERIMENTO/CONTENUTO/VALORE vengono propagati, non è necessario specificare BY se tutti sono uguali e si desidera che, PER RIFERIMENTO, è l'impostazione predefinita.

Se si "passa" a POINTER (USAGE POINTER), è possibile accedere ai dati indicati utilizzando SET ADDRESS OF. L'articolo SET ADDRESS OF deve essere nel numero LINKAGE SECTION.

È inoltre possibile utilizzare un puntatore implicito con SET ADDRESS OF. IMPOSTA INDIRIZZO DI UN INDIRIZZO A DI b cambierà l'indirizzo mappato nella SEZIONE COLLEGAMENTO all'indirizzo b, un elemento definito da qualche parte nel programma DATA DIVISION (qualsiasi SEZIONE diversa da FILE SECTION).

Se si desidera visualizzare i dati puntati da un POINTER, definire un elemento che ha le dimensioni e il tipo corretti e utilizzare IMPOSTA INDIRIZZO DELLA voce TO nome-puntatore.

Il POINTER può ovviamente puntare a una semplice voce di dati oa un gruppo di dati (una struttura).

Tutti gli articoli nella SEZIONE COLLEGAMENTO devono avere un indirizzo prima di essere referenziati. Quelli su un UTILIZZO sono dati indirizzabilità dal compilatore (e il compilatore presuppone che sia passato il numero corretto di indirizzi/elementi). Tutte le altre voci della SEZIONE COLLEGAMENTO devono avere l'indirizzabilità stabilita da INDIRIZZO SET o passando INDIRIZZO DI nell'USO di un CALL e con il programma Chiamata impostato l'indirizzo.

+0

Grazie mille. Il callback funziona ora. –