ホームページ  >  記事  >  バックエンド開発  >  CGO プロジェクトでよく使用されるデータ変換と使用方法の詳細な説明

CGO プロジェクトでよく使用されるデータ変換と使用方法の詳細な説明

藏色散人
藏色散人転載
2022-01-20 17:06:043915ブラウズ

この記事は、golang のチュートリアル コラムから提供され、CGO の実践プロジェクトでよく使用されるデータ変換と使用方法を紹介するものです。必要!

まえがき

関連する環境をデプロイし、基本的な知識を習得する必要があります。これは一般的な科学記事ではなく、主に実際のプロジェクトで使用される種類のものです。 . 動的ライブラリの関数呼び出しパラメータ送受信のための変換と利用
1. GO 環境、CGO のサポート開始
2. 事前に g をインストール
3. GO と C## の構文を理解する#4 、主に C を自分でデバッグするときに使用する必要があるため、基本的な makefile またはシェル構文を知っておくのが最善です (つまり、私は理解できません。初心者で、大まかな概要しか読めません)。 ## すべてを知っている場合は、リテラシー リンクをクリックしてください:chai2010.cn/advanced-go-programmin...

基本データ型のリスト

##GO は C 言語の呼び出しをサポートしているため、C での変換のみがリストされていますが、C については、正常に呼び出す前に C 言語に変換する必要があります。各 C 変数は 1 つのパッケージ内での使用に制限されていることに注意してください。パッケージ間で使用したい場合は、GO を使用してカプセル化してください。そうでない場合は、呼び出しエラーが表示され、C 変数が見つかりません。

CGO プロジェクトでよく使用されるデータ変換と使用方法の詳細な説明

プロジェクトで使用されるデータ型変換

#Go 文字列は C に変換されます

C 文字列は 1 文字です配列の場合は、簡単に言えば、0 で終わる文字配列は文字列であるため、基本データ型には属しません。 C.CString は C を呼び出す標準ライブラリです。これは新しいメモリ空間に適用され、解放するには C.free を呼び出す必要があります。そうしないとメモリ リークが発生します。
    var  deviceIp string
    cdeviceIp := C.CString(deviceIp)
    defer C.free(unsafe.Pointer(cdeviceIp))


C の char * /char[] は go の string に変換されます

C の標準ライブラリ C.GoString を呼び出します。この関数は新しいメモリ空間を生成しません。コピーしますが、メモリ領域は解放されません。

C バイト配列を Go 文字列に変換します

たとえば、C の型は次のとおりです: BYTE sSerialNumber[SERIALNO_LEN];これを取得する方法は次のとおりです。 append を使用して文字列にバイトを追加します
    serialNo := make([]byte, 0)
    for _, v := range sSerialNumber {
        if v != 0 {
            serialNo = append(serialNo, byte(v))
        }
    }

前述の文字配列と文字列の違いに注意してください。


文字列を C 文字配列に移動

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

結合データ取得

Huawei カメラのデータ コールバックに接続すると、共用体型のデータが取得されます。通常の構造体として取得すると、コンパイラは常に構造体が見つからないことを示すメッセージを表示します。 Cコード 共用体のデータを取得後、基本データ型に変換して、再度Goを呼び出します。コード スニペットを投稿して、顔認識コールバックからデータを取得します。コンテキストは気にせず、データ型を取得する方法だけを見てください。
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 ;}
このコードを Go ロジックに置き換えて Go で直接読み取ると、unMetaData が定義を見つけられないというメッセージが表示されます。他に成功する読み取り方法があれば、お知らせください。

C

コールバック関数を C

1 で呼び出します。まず、同じデータ型の関数を Go コードに実装し、//export を使用して C 関数としてエクスポートします。コールバックが見つからない場合は、まずデータ型が正しいかどうかを確認し、次にトリガー条件が満たされているかどうかを確認します。このステップはC言語のコールバックデータ、つまりこの関数で取得したコールバック後のデータをGo言語で受け取るステップです。

2. CGO は C 関数を呼び出します。一部の同僚は、このステップは省略できると言っています。最初のステップの関数を Go で直接呼び出すだけで済みます。私はまだ試していません。会社の祖先のコードは次のように書かれています。これをフォローするだけです。
3. GO 言語の共通関数として直接呼び出すだけです。
コード例を見てください:
C 関数宣言:

typedef VOID (CALLBACK *pfRealDataCallBack)(CHAR *szBuffer, LONG lSize, VOID *pUsrData);
最初のステップのコード:

//export GopfRealDataCallBackfunc GopfRealDataCallBack(szBuffer *C.CHAR, lSize C.LONG, pUsrData unsafe.Pointer) {
    fmt.Println(szBuffer,lSize,pUsrData)}
2 番目のステップ:

extern void GopfRealDataCallBack(CHAR *szBuffer, LONG lSize, void *pUsrData);void CGopfRealDataCallBack(CHAR *szBuffer, LONG lSize, void *pUsrData){
    return GopfRealDataCallBack(szBuffer,lSize,pUsrData);}
3 番目のステップステップ: C.pfRealDataCallBack(C.CGopfRealDataCallBack) をインポート C で宣言する必要があります。宣言しない場合、呼び出しは有効になりません

void* および unsafe.Pointer

unsafe .Pointer は、すべてのデータ型転送ブリッジとして知られており、言語レベルで同等と見なすことができます。void* が発生した場合、unsafe.Pointer を使用して受信または送信できます。特定の型の変換には、実際の型に基づいた強制変換が必要です。例:

lpOutBuff := unsafe.Pointer(C.malloc(1024))
この 1024 は実際の状況に基づいて変更できますが、万能薬ではありません。

结构体数组的传递

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>

以上がCGO プロジェクトでよく使用されるデータ変換と使用方法の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はlearnku.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。