以下の内容はhttps://devlights.hatenablog.com/entry/2025/10/01/073000より取得しました。


Goメモ-623 (cgoメモ-29)(memcpyの呼び出し)

関連記事

Goメモ-502 (cgoメモ-01)(cgoヘッダ) - いろいろ備忘録日記

Goメモ-506 (cgoメモ-02)(cgoヘッダ) - いろいろ備忘録日記

Goメモ-507 (cgoメモ-03)(C.int) - いろいろ備忘録日記

Goメモ-508 (cgoメモ-04)(C言語の構造体) - いろいろ備忘録日記

Goメモ-509 (cgoメモ-05)(C.CString)(Cの文字列) - いろいろ備忘録日記

Goメモ-510 (cgoメモ-06)(C.GoString)(Cの文字列をGoの文字列へ) - いろいろ備忘録日記

Goメモ-511 (cgoメモ-07)(C.CBytes)([]byteをCのバイト列に) - いろいろ備忘録日記

Goメモ-512 (cgoメモ-08)(C.GoBytes)(Cのバイト列をGoの[]byteへ) - いろいろ備忘録日記

Goメモ-514 (cgoメモ-09)(C.GoStringN)(C.GoStringのサイズ指定版) - いろいろ備忘録日記

Goメモ-515 (cgoメモ-10)([]byteを(void *)へ変換) - いろいろ備忘録日記

Goメモ-516 (cgoメモ-11)([]byteを(char *)へ変換) - いろいろ備忘録日記

Goメモ-518 (cgoメモ-12)(Cのmallocをcgo経由で呼び出し) - いろいろ備忘録日記

Goメモ-519 (cgoメモ-13)(ポインタ演算) - いろいろ備忘録日記

Goメモ-520 (cgoメモ-14)(Goの関数をCの世界に公開 (export)) - いろいろ備忘録日記

Goメモ-522 (cgoメモ-15)(Goでsoファイルを作成してC言語から呼び出し) - いろいろ備忘録日記

Goメモ-525 (cgoメモ-16)(C側にて関数ポインタを引数に要求する関数にGo側で定義した関数を設定) - いろいろ備忘録日記

Goメモ-526 (cgoメモ-17)(cgoとdlopen関数を使って既存ライブラリの呼び出しをフックする) - いろいろ備忘録日記

Goメモ-527 (cgoメモ-18)(cgoを利用している場合のinit関数について) - いろいろ備忘録日記

Goメモ-528 (cgoメモ-19)(cgoを利用して作成したsoファイル経由でのinit関数の呼び出し) - いろいろ備忘録日記

Goメモ-529 (cgoメモ-20)(C言語のNULLをcgoから渡す) - いろいろ備忘録日記

Goメモ-530 (cgoメモ-21)(CGOヘッダーで指定出来るCFLAGS, LDFLAGS) - いろいろ備忘録日記

Goメモ-531 (cgoメモ-22)(CGOで利用するコンパイラを変更する) - いろいろ備忘録日記

Goメモ-532 (cgoメモ-23)(CGOヘッダで使えるSRCDIR変数) - いろいろ備忘録日記

Goメモ-534 (cgoメモ-24)(C側の構造体にて固定要素数の文字配列をGo側で文字列に変換) - いろいろ備忘録日記

Goメモ-535 (cgoメモ-25)(cgo.Handleを用いてCとGoの間で値をやり取りする) - いろいろ備忘録日記

Goメモ-536 (cgoメモ-26)(C側の構造体をGo側で利用する) - いろいろ備忘録日記

Goメモ-537 (cgoメモ-27)(Go側でCの構造体のサイズを知る方法) - いろいろ備忘録日記

Goメモ-539 (cgoメモ-28)(Go側でCの文字列リスト(**char)を扱う) - いろいろ備忘録日記

GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ

概要

以下、自分用のメモです。

今回から複数回に渡って cgo についてメモしていこうと思います。

cgo は、文字通りGoからCにアクセスすることが出来るようになるものなのですが、とても便利な反面、結構クセが強いのでメモでも残しておかないとすぐ頭から消えてしまいそうだなって思いました。

Cgo is not Go

という格言があったりするので、Go界隈で標準で推奨されていない技術かもしれません。が、実務ではC言語で作成されたライブラリなどは山のようにあります。んで、プロジェクトの方針でGoで作り直すことも出来ない場合も多々あります。そのような場合に非常に便利です。

これからのサンプルは以下のリポジトリにアップしてありますので、良ければご参考ください。

github.com

今回は C言語でおなじみのmemcpyの呼び出しについて。

cgoで実装しているGoの関数の中でC側のデータに対して作った値をセットしたりする場合によく利用したりします。

サンプル

main.go

package main

/*
#cgo CFLAGS: -Wall -std=c99
#cgo LDFLAGS:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
*/
import "C"
import (
    "strings"
    "unsafe"
)

//export mymemcpy
func mymemcpy(dst *C.char, src *C.char, n C.size_t) {
    //
    // memcpy関数のシグネチャは
    //   void *memcpy(void *dest, const void *src, size_t n);
    // となっている。
    //
    // cgo側から見ると以下のように見える。
    //   func memcpy(dst unsafe.Pointer, src unsafe.Pointer, n C.size_t) (r1 unsafe.Pointer)
    //
    // (void *) は、cgoでは、unsafe.Pointer となるため
    // 指定する値の型が (char *) つまり、(*C.char) の場合は
    // unsafe.Pointer(*C.char)に変換して渡す。
    //

    // 元文字列を大文字に変換してmemcpyする
    //   - C.GoString()とC.CString()については、サンプル「06.C_GoString」を参照。

    var (
        goStr = strings.ToUpper(C.GoString(src))
        cStr  = unsafe.Pointer(C.CString(goStr))
    )
    defer C.free(cStr)

    var (
        pDst = unsafe.Pointer(dst)
    )
    C.memcpy(pDst, cStr, n)
}

func main() {}

app.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern void mymemcpy(char *dst, char *src, size_t n);

#define STR ("helloworld")

int main(void)
{
    size_t n = sizeof(STR);
    char   dst[n];

    memset(dst, 0, sizeof(dst));

    printf("[before] %s:%s\n", STR, dst);
    {
        mymemcpy(dst, STR, n);
    }
    printf("[after ] %s:%s\n", STR, dst);

    return EXIT_SUCCESS;
}

Taskfile.yml

# https://taskfile.dev

version: '3'

tasks:
  default:
    cmds:
      - rm -f app liba.*
      - go build -o liba.a -buildmode=c-archive main.go
      - gcc -Wall -o app app.c liba.a
      - ./app

実行

$ task
task: [default] rm -f app liba.*
task: [default] go build -o liba.a -buildmode=c-archive main.go
task: [default] gcc -Wall -o app app.c liba.a
task: [default] ./app
[before] helloworld:
[after ] helloworld:HELLOWORLD

参考情報

個人的Goのおすすめ書籍

個人的に読んでとても勉強になった書籍さんたちです。


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。




以上の内容はhttps://devlights.hatenablog.com/entry/2025/10/01/073000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14