Heim >Backend-Entwicklung >Golang >Detaillierte Erläuterung der häufig verwendeten Datenkonvertierung und -verwendung in CGO-Projekten

Detaillierte Erläuterung der häufig verwendeten Datenkonvertierung und -verwendung in CGO-Projekten

藏色散人
藏色散人nach vorne
2022-01-20 17:06:043958Durchsuche

Dieser Artikel wird in der Tutorial-Kolumne von golang bereitgestellt, um Ihnen die häufig verwendete Datenkonvertierung und -verwendung in praktischen CGO-Projekten vorzustellen. Ich hoffe, dass er Freunden in Not hilfreich sein wird!

Vorwort

Sie müssen die entsprechende Umgebung bereitstellen und über grundlegende Wissenspunkte verfügen. Dies ist kein populärwissenschaftlicher Artikel. Er dient hauptsächlich der Typkonvertierung und der Verwendung in tatsächlichen Projekten sowie der Übergabe von Funktionsaufrufparametern an dynamische Bibliotheken. und erhalten Sie
1. Start unterstützt CGO
3. Verstehen Sie die Syntax von GO und C
4 Ich bin ein Neuling, ich kann es nur grob betrachten.) Es wird hauptsächlich zum Debuggen von C selbst verwendet
Liste der grundlegenden Datentypen

Da GO den Aufruf in C-Sprache unterstützt, wird nur die Konvertierung in C aufgeführt. Was C++ betrifft, muss es in die C-Sprache konvertiert werden, bevor es erfolgreich aufgerufen werden kann. Es ist zu beachten, dass jede C-Variable nur innerhalb eines Pakets verwendet werden kann. Wenn Sie sie paketübergreifend verwenden möchten, verwenden Sie bitte GO, um sie zu kapseln. Andernfalls wird ein Aufruffehler angezeigt und die C-Variable kann nicht gefunden werden.

Detaillierte Erläuterung der häufig verwendeten Datenkonvertierung und -verwendung in CGO-Projekten

Die im Projekt verwendete Datentypkonvertierung

go-String-Konvertierung in C

C-String ist ein Sonderfall eines Zeichenarrays. Einfach ausgedrückt ist ein Array von Zeichenarrays, die mit 0 enden, ein String es gehört nicht zum Basisdatentyp.
C.CString ist eine Standardbibliothek, die C aufruft. Sie beantragt neuen Speicherplatz und muss C.free aufrufen, um ihn freizugeben, da sonst Speicherverluste auftreten.
    var  deviceIp string
    cdeviceIp := C.CString(deviceIp)
    defer C.free(unsafe.Pointer(cdeviceIp))

Cs char * /char[] wird in gos String umgewandelt

Call Cs Standardbibliothek C.GoString. Diese Funktion generiert keinen neuen Speicherplatz, sie erstellt eine Kopie und gibt den Speicherplatz nicht frei .
Konvertieren Sie das C-Byte-Array in einen Go-String

Der Typ von C ist beispielsweise: BYTE sSerialNumber[SERIALNO_LEN];

Der Weg, ihn zu erhalten, besteht darin, mit append Bytes zum String hinzuzufügen
    serialNo := make([]byte, 0)
    for _, v := range sSerialNumber {
        if v != 0 {
            serialNo = append(serialNo, byte(v))
        }
    }
Achten Sie darauf die zuvor erwähnten Zeichen Der Unterschied zwischen Arrays und Strings.


Gehe von der Zeichenfolge zum C-Zeichen-Array

Typ: CHAR szKeyFilePath[PU_CERT_FILE_PATH_MAX];

    var keyFilePath = "/home/docker/path/file.jpg"
    for i, b := range keyFilePath {
        szKeyFilePath[i] = C.CHAR(b)
    }

Konsortium-Datenerfassung

Beim Empfang des Datenrückrufs von der Huawei-Kamera erfolgt eine Datenerfassung vom Typ Konsortium Als normale Struktur meldet der Compiler immer, dass die Struktur nicht gefunden werden kann. Konvertieren Sie die Unionsdaten im C-Code als letzten Ausweg in den Basisdatentyp und rufen Sie dann erneut Go auf. Veröffentlichen Sie einen Codeausschnitt, um die Daten aus dem Rückruf zur Gesichtserkennung abzurufen. Machen Sie sich keine Gedanken über den Kontext, schauen Sie sich einfach an, wie Sie den Datentyp erhalten.

void CGopfFaceSnapCallBack(CHAR *szBuffer, LONG lSize, void *pUsrData) {
    PU_META_DATA *pstMetaData = 0;
    int ret = Wrapper_IVS_User_GetMetaData(szBuffer, lSize, TARGET, &pstMetaData);
    if (ret == PU_FALSE ){
        return ;
    }
    PU_UserData *pstMetaUserData = pstMetaData->pstMetaUserData;
    char  name[100]={0};
    char  cardID[100]={0};
    for(UINT uIndex = 0; uIndex usValidNumber; ++uIndex){
       //printf("pstMetaData eType : %x\n", pstMetaUserData[uIndex].eType);
        if (pstMetaUserData[uIndex].eType == FACE_INFO){
            strcpy(cardID, pstMetaUserData[uIndex].unMetaData.stFaceInfo.cardID);
            strcpy(name, pstMetaUserData[uIndex].unMetaData.stFaceInfo.name);
            printf("GopfFaceSnapCallBack unMetaData.stFaceInfo cardID : %s\n", pstMetaUserData[uIndex].unMetaData.stFaceInfo.cardID);
            printf("GopfFaceSnapCallBack unMetaData.stFaceInfo name : %s\n", pstMetaUserData[uIndex].unMetaData.stFaceInfo.name);
            GopfFaceSnapCallBack(pstMetaUserData[uIndex].unMetaData.stFaceInfo.cardID,pUsrData);
            break ;
        }
    }
    Wrapper_IVS_User_FreeMetaData(&pstMetaData);
    return ;}
Wenn dieser Code durch Go-Logik ersetzt und direkt in Go gelesen wird, wird angezeigt, dass unMetaData die Definition nicht finden kann. Wenn es andere erfolgreiche Lesemethoden gibt, teilen Sie uns dies bitte mit.

Callback-Funktionsaufruf in C

1 Implementieren Sie zunächst die Funktion mit demselben Datentyp im Go-Code und exportieren Sie sie mit //export als C-Funktion. Überprüfen Sie zunächst, ob der Datentyp korrekt ist, und überprüfen Sie dann den Trigger. Ob die Bedingungen erfüllt sind. In diesem Schritt werden die Rückrufdaten der C-Sprache in der Go-Sprache empfangen, dh die Rückrufdaten werden in dieser Funktion abgerufen.

2. Einige Kollegen sagten, dass dieser Schritt im ersten Schritt weggelassen werden kann. Ich habe es noch nicht ausprobiert Benutze es einfach. 3. Rufen Sie es einfach direkt als allgemeine Funktion in der GO-Sprache auf. Sehen Sie sich das Codebeispiel an:

C-Funktionsdeklaration:

typedef VOID (CALLBACK *pfRealDataCallBack)(CHAR *szBuffer, LONG lSize, VOID *pUsrData);

Der erste Schritt des Codes:
//export GopfRealDataCallBackfunc GopfRealDataCallBack(szBuffer *C.CHAR, lSize C.LONG, pUsrData unsafe.Pointer) {
    fmt.Println(szBuffer,lSize,pUsrData)}

Der zweite Schritt:
extern void GopfRealDataCallBack(CHAR *szBuffer, LONG lSize, void *pUsrData);void CGopfRealDataCallBack(CHAR *szBuffer, LONG lSize, void *pUsrData){
    return GopfRealDataCallBack(szBuffer,lSize,pUsrData);}
Der dritte Schritt: C.pfRealDataCallBack (C.CGopfRealDataCallBack) muss am deklariert werden import C, Andernfalls wird der Aufruf nicht wirksam

void* und unsafe.Pointer

unsafe.Pointer wird als Übertragungsbrücke für alle Datentypen bezeichnet void* wird angetroffen, unsicher. Der Zeiger kann beim Empfangen oder Senden verwendet werden. Die Konvertierung bestimmter Typen erfordert eine erzwungene Konvertierung basierend auf dem tatsächlichen Typ. Zum Beispiel:

lpOutBuff := unsafe.Pointer(C.malloc(1024))
Dieser 1024 kann je nach tatsächlicher Situation geändert werden und ist kein Allheilmittel.

结构体数组的传递

results := (*C.struct_name)(C.malloc(C.size_t(C.sizeof_struct_name * C.int(resLen))))
    defer C.free(unsafe.Pointer(results))

struct_name换成具体的结构体名称,申请了空间要释放,GO检测不到C的部分。

结构体数组遍历获取元素数据

    for i := 0; i <p>struct_name换成具体的结构体名称,uintptr是元素内存地址,根据偏移量获取元素。<code>go
    for i := 0; i <span class="rm-link-color">                      </span>                             </code></p><p class="meta" style="margin: 35px 0px;"><em class="icon tags"></em></p>

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der häufig verwendeten Datenkonvertierung und -verwendung in CGO-Projekten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:learnku.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen