SlideShare una empresa de Scribd logo
1 de 17
Descargar para leer sin conexión
Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
denoでFFI



虎の穴ラボ 藤原 佳顕

1
Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
アジェンダ

● 概要
● やりたかったこと
● ソースを見てみよう
● 作ってみよう
2
Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
自己紹介

3
● 名前

○ 藤原佳顕(@nuhera, @zonuko)

● 仕事

○ FantiaとかCreatiaとか社内アプリとか

● 好み

○ Clojure、Rust

● 趣味

○ 格闘ゲーム

■ Melty Blood、Guilty Gear

○ STG(ダライアスとか)も好き

○ 最近は女神転生Vずっとやってました

Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
概要

4
● deno1.13あたりからFFI機能が追加されています


○ what’s ffi?

■ 別の言語で作られた関すなどをまた別の言語から呼び出せる機能


■ deno固有の言葉ではない

○ これによってDLLやSOファイルなど、いわゆるダイナミック/スタティックライブラリを
Denoから呼び出せるように

Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
概要

5
● 代表的なライブラリ

○ と言われて何が思い浮かびますか?


○ libmysqlclient.so

○ RTP

■ RPGツクールのランタイムライブラリ群


○ Win32 DLL (kernel32.dll、user32.dll、gdi32.dllなど)


Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
やりたかったこと

● DenoにFFIが入ったということはlibmysqlclient経由でmysql接続できるのでは?

● mysqlの接続方法自体はいくつかある

○ TCP接続

○ Unix Domain Socket接続

○ 名前付きパイプ

■ プロセス間通信で一般的に使われるやつ





6
Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
やりたかったこと

● とはいえDenoにはmysql用のライブラリがすでにある

○ https://deno.land/x/mysql@v2.10.1





7
private async _connect() {
// TODO: implement connect timeout
const { hostname, port = 3306, socketPath, username = "", password } = this.config;
log.info(`connecting ${this.remoteAddr}`);
this.conn = !socketPath
? await Deno.connect({
transport: "tcp",
hostname,
port,
})
: await Deno.connect({
transport: "unix",
path: socketPath,
} as any);
…
mysqlがインストールされているかに関わらず、tcp/ドメイ
ンソケット経由なのがわかる



Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
やりたかったこと



● ではDenoでのFFIするときにインターフェースはどうなっているか

○ ソースはこんな感じ











● 対応している型はchar / signed char, unsigned char, short int, unsigned short int, int / signed int, unsigned int, long long int,
unsigned long long int, size_t, float, double, void, const uint8_t *

○ https://deno.land/manual@main/runtime/ffi_api



8
const libName = `./libadd.${libSuffix}`;
// Open library and define exported symbols
const dylib = Deno.dlopen(libName, {
"add": { parameters: ["isize", "isize"], result: "isize" },
});
Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
やりたかったこと



● 一方でlibmysql側のインターフェースは?


○ 例:コネクション貼りたい場合

■ https://dev.mysql.com/doc/refman/5.6/ja/mysql-real-connect.html


■ MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char
*user, const char *passwd, const char *db, unsigned int port, const
char *unix_socket, unsigned long client_flag)
■ MYSQL構造体が出てきているので現段階ではうまく扱えなさそう


● →とりあえず他の言語でどうやっているか見てみよう


9
Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
ソースを見てみよう

● mysqlといえばRails

○ https://github.com/brianmario/mysql2

● Rubyには拡張ライブラリという仕組みがあります

○ https://docs.ruby-lang.org/en/2.4.0/extension_ja_rdoc.html

○ ルール基づいて作られたCライブラリをRuby側から一本のクラスやモジュールであるかのように呼び出せる

○ 抜粋

■ rb_define_module:新しいモジュール定義

■ rb_define_class_under: あるクラスを継承したクラスをモジュール配下に定義

■ rb_define_method:クラスにメソッドを定義

■ rb_define_private_method: クラスにプライベートメソッドを定義

○ Ruby側でどこからともなくconnectionメソッドが呼ばれているので、rb_define_method、rb_define_private_methodあたりで検
索かければなにかでてくるのでは?

10
Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
ソースを見てみよう

● https://github.com/brianmario/mysql2/blob/6652da20010ddfbbe6bceb8e41666d05e512346c/ext/mysql2/client.c#L445

● 最終的な部分

11
static void *nogvl_connect(void *ptr) {
struct nogvl_connect_args *args = ptr;
MYSQL *client;
client = mysql_real_connect(args->mysql, args->host,
args->user, args->passwd,
args->db, args->port, args->unix_socket,
args->client_flag);
return (void *)(client ? Qtrue : Qfalse);
}
=>直接libmysqlclient.soとかを呼び出していることはなく、C言語等でラップされている 

Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
作ってみよう

● まずはコネクション取得(C側)

○ mysql_init→mysql_real_connectとする必要があるのでどちらのラッパー関数も定義(ついでにcloseも)

12
#include <mysql/mysql.h>
#include <stdio.h>
MYSQL *conn = NULL;
void init()
{
conn = mysql_init(NULL);
}
int connect(const char *host, const char *user, const char *passwd, const char *db_name, int port)
{
if (!mysql_real_connect(conn, host, user, passwd, db_name, port, NULL, 0)) {
fprintf(stderr, "Failed to connect to database: Error: %sn", mysql_error(conn));
fflush(stderr);
return 0;
}
return 1;
}
void close(void)
{
mysql_close(conn);
}
Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
作ってみよう

● ネクション取得(deno側)

13
const C_TERMINAL_SYMBOL = "0";
const MYSQL_HOST = "localhost";
const MYSQL_USER = "root";
const MYSQL_PASSWD = "";
const MYSQL_DB_NAME = "mysql";
const MYSQL_PORT = 3306;
function strToBytes(word: string): Uint8Array {
return new TextEncoder().encode(`${word}${C_TERMINAL_SYMBOL}`);
}
function ffiSuffix(): string {
switch (Deno.build.os) {
case "windows":
return "dll";
case "darwin":
return "dylib";
case "linux":
return "so";
}
}
interface LibInterfaces extends Record<string, Deno.ForeignFunction> {
init: Deno.ForeignFunction;
connect: Deno.ForeignFunction;
close: Deno.ForeignFunction;
}
const libInterfaces: LibInterfaces = {
init: { parameters: [], result: "void" },
connect: {
parameters: ["buffer", "buffer", "buffer", "buffer", "i32"],
result: "i32",
},
close: { parameters: [], result: "void" },
};
Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
作ってみよう

● コネクション取得続き(deno側)

14
class MySQL {
#dylib: Deno.DynamicLibrary<LibInterfaces> | null = null;
readonly host = strToBytes(MYSQL_HOST);
readonly user = strToBytes(MYSQL_USER);
readonly passwd = strToBytes(MYSQL_PASSWD);
readonly dbName = strToBytes(MYSQL_DB_NAME);
private isConn = false;
constructor() {
const libName = `./ext/mysql/mysql.${ffiSuffix()}`;
this.#dylib = Deno.dlopen(libName, libInterfaces);
this.#dylib.symbols.init();
const res = this.#dylib.symbols.connect(this.host, this.user, this.passwd, this.dbName, MYSQL_PORT);
if (res === 0) {
this.close();
throw new Error("コネクション確立に失敗しました。 ");
}
this.isConn = true;
}
close() {
if (!this.#dylib) {
return;
}
if (this.isConn) {
this.#dylib.symbols.close();
this.#dylib.close();
this.#dylib = null;
}
}
}
const client = new MySQL();
client.close();
Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
作ってみよう

● 動かしてみる

○ libmysqlclient.(so|dll|dylib)のフォルダを指定してコンパイルする必要がある

○ 今回はコネクション貼って即時クローズするので、例外がでなければとりあえずOK

15
> gcc -c -fPIC -o ./ext/mysql/mysql.o ./ext/mysql/mysql.c
> gcc -shared -W -o ./ext/mysql/mysql.so ./ext/mysql/mysql.o -L/usr/lib/x86_64-linux-gnu -lmysqlclient
> deno run --unstable --allow-ffi mod.ts
(macの場合はlibフォルダが異なるので -L/usr/local/lib などとする)

Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
課題とハマったところ

● たまに接続文字列の後ろにゴミがくっついてエラーになる(“127.0.0.1L”とか)

○ bufferに文字列食わせるときに終端文字が必要だった(0)

○ C言語で文字列扱う場合は必要な処理だがDeno側に必要なのは盲点だった

● queryの結果取得が面倒

○ mysql_real_query→mysql_use_resultで結果取得といった流れ

○ mysql_use_resultの戻り値がMYSQL_RES構造体なのでこれもそのままは扱えない

○ また、まだbufferを戻り値にできない→クエリ実行結果を文字列としては戻せない

● そもそもRustでlibmysqlclientをラップしたほうが楽では?

○ こちらであればdeno_bindgenが使える

○ https://deno.land/manual@v1.16.3/runtime/ffi_api

16
Copyright  (C) 2021 Toranoana Inc. All Rights Reserved.
まとめ

● そのままでは複雑な構造体をI/Fとして持つものをFFIすることは難しそう


● CやC++でさらに使いたいdllやsoファイルをラップする必要がありそう


○ Cのグローバルにconnectionとか置かないとダメそう


■ Cの中だけに収まってくれるか?という勝負


● ただし、やり方さえ確立できればどんなものでもFFIできそう


● より細かい話は12/4に公開するアドベントカレンダーのブログで紹介しています。


17

Más contenido relacionado

La actualidad más candente

【とらのあなラボ Tech Day #3】新規システムにおける技術選定〜GoとgRPCを採用した話〜
【とらのあなラボ Tech Day #3】新規システムにおける技術選定〜GoとgRPCを採用した話〜	【とらのあなラボ Tech Day #3】新規システムにおける技術選定〜GoとgRPCを採用した話〜
【とらのあなラボ Tech Day #3】新規システムにおける技術選定〜GoとgRPCを採用した話〜 虎の穴 開発室
 
Webアプリケーション開発者のためのDockerハンズオン
Webアプリケーション開発者のためのDockerハンズオンWebアプリケーション開発者のためのDockerハンズオン
Webアプリケーション開発者のためのDockerハンズオン虎の穴 開発室
 
Shadow Server on Fluentd at Fluentd Casual Talks #3
Shadow Server on Fluentd at Fluentd Casual Talks #3Shadow Server on Fluentd at Fluentd Casual Talks #3
Shadow Server on Fluentd at Fluentd Casual Talks #3Naotoshi Seo
 
最近僕が使うようになったPerl 5.10以降の新しいやつ
最近僕が使うようになったPerl 5.10以降の新しいやつ最近僕が使うようになったPerl 5.10以降の新しいやつ
最近僕が使うようになったPerl 5.10以降の新しいやつazumakuniyuki 🐈
 
ドリコムを支える課金ライブラリを支えるJenkins
ドリコムを支える課金ライブラリを支えるJenkinsドリコムを支える課金ライブラリを支えるJenkins
ドリコムを支える課金ライブラリを支えるJenkinsGo Sueyoshi (a.k.a sue445)
 
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツールPyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツールAtsuo Ishimoto
 
【20211022_toranoana@LT#Vue3】Vue2からVue3にして困ったところ
【20211022_toranoana@LT#Vue3】Vue2からVue3にして困ったところ【20211022_toranoana@LT#Vue3】Vue2からVue3にして困ったところ
【20211022_toranoana@LT#Vue3】Vue2からVue3にして困ったところ虎の穴 開発室
 
社内ツールが支えるドリコムの社内勉強会文化 #metabenkyokai
社内ツールが支えるドリコムの社内勉強会文化 #metabenkyokai社内ツールが支えるドリコムの社内勉強会文化 #metabenkyokai
社内ツールが支えるドリコムの社内勉強会文化 #metabenkyokaiGo Sueyoshi (a.k.a sue445)
 
JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2
JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2
JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2azumakuniyuki 🐈
 
Pelicanによる www.python.jpの構築
Pelicanによる www.python.jpの構築Pelicanによる www.python.jpの構築
Pelicanによる www.python.jpの構築Atsuo Ishimoto
 
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...Yoshifumi Kawai
 
Resemaraを支えた技術 フライングゲットガチャの舞台裏 #ksgstudy #ドリコム
Resemaraを支えた技術 フライングゲットガチャの舞台裏 #ksgstudy #ドリコムResemaraを支えた技術 フライングゲットガチャの舞台裏 #ksgstudy #ドリコム
Resemaraを支えた技術 フライングゲットガチャの舞台裏 #ksgstudy #ドリコムGo Sueyoshi (a.k.a sue445)
 
Markup Template Engine introduced Groovy 2.3
Markup Template Engine introduced Groovy 2.3Markup Template Engine introduced Groovy 2.3
Markup Template Engine introduced Groovy 2.3Uehara Junji
 
AWS SDK for Smalltalk
AWS SDK for SmalltalkAWS SDK for Smalltalk
AWS SDK for SmalltalkSho Yoshida
 
Introduce Groovy 2.3 trait
Introduce Groovy 2.3 trait Introduce Groovy 2.3 trait
Introduce Groovy 2.3 trait Uehara Junji
 

La actualidad más candente (20)

【とらのあなラボ Tech Day #3】新規システムにおける技術選定〜GoとgRPCを採用した話〜
【とらのあなラボ Tech Day #3】新規システムにおける技術選定〜GoとgRPCを採用した話〜	【とらのあなラボ Tech Day #3】新規システムにおける技術選定〜GoとgRPCを採用した話〜
【とらのあなラボ Tech Day #3】新規システムにおける技術選定〜GoとgRPCを採用した話〜
 
Rake
RakeRake
Rake
 
Webアプリケーション開発者のためのDockerハンズオン
Webアプリケーション開発者のためのDockerハンズオンWebアプリケーション開発者のためのDockerハンズオン
Webアプリケーション開発者のためのDockerハンズオン
 
Shadow Server on Fluentd at Fluentd Casual Talks #3
Shadow Server on Fluentd at Fluentd Casual Talks #3Shadow Server on Fluentd at Fluentd Casual Talks #3
Shadow Server on Fluentd at Fluentd Casual Talks #3
 
最近僕が使うようになったPerl 5.10以降の新しいやつ
最近僕が使うようになったPerl 5.10以降の新しいやつ最近僕が使うようになったPerl 5.10以降の新しいやつ
最近僕が使うようになったPerl 5.10以降の新しいやつ
 
オタク×Node.js勉強会
オタク×Node.js勉強会オタク×Node.js勉強会
オタク×Node.js勉強会
 
ドリコムを支える課金ライブラリを支えるJenkins
ドリコムを支える課金ライブラリを支えるJenkinsドリコムを支える課金ライブラリを支えるJenkins
ドリコムを支える課金ライブラリを支えるJenkins
 
2018/2/20 Kotlin勉強会
2018/2/20 Kotlin勉強会2018/2/20 Kotlin勉強会
2018/2/20 Kotlin勉強会
 
ドリコムのインフラCI
ドリコムのインフラCIドリコムのインフラCI
ドリコムのインフラCI
 
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツールPyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール
 
【20211022_toranoana@LT#Vue3】Vue2からVue3にして困ったところ
【20211022_toranoana@LT#Vue3】Vue2からVue3にして困ったところ【20211022_toranoana@LT#Vue3】Vue2からVue3にして困ったところ
【20211022_toranoana@LT#Vue3】Vue2からVue3にして困ったところ
 
社内ツールが支えるドリコムの社内勉強会文化 #metabenkyokai
社内ツールが支えるドリコムの社内勉強会文化 #metabenkyokai社内ツールが支えるドリコムの社内勉強会文化 #metabenkyokai
社内ツールが支えるドリコムの社内勉強会文化 #metabenkyokai
 
JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2
JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2
JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2
 
Pelicanによる www.python.jpの構築
Pelicanによる www.python.jpの構築Pelicanによる www.python.jpの構築
Pelicanによる www.python.jpの構築
 
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
 
Resemaraを支えた技術 フライングゲットガチャの舞台裏 #ksgstudy #ドリコム
Resemaraを支えた技術 フライングゲットガチャの舞台裏 #ksgstudy #ドリコムResemaraを支えた技術 フライングゲットガチャの舞台裏 #ksgstudy #ドリコム
Resemaraを支えた技術 フライングゲットガチャの舞台裏 #ksgstudy #ドリコム
 
Markup Template Engine introduced Groovy 2.3
Markup Template Engine introduced Groovy 2.3Markup Template Engine introduced Groovy 2.3
Markup Template Engine introduced Groovy 2.3
 
AWS SDK for Smalltalk
AWS SDK for SmalltalkAWS SDK for Smalltalk
AWS SDK for Smalltalk
 
Introduce Groovy 2.3 trait
Introduce Groovy 2.3 trait Introduce Groovy 2.3 trait
Introduce Groovy 2.3 trait
 
Rust-DPDK
Rust-DPDKRust-DPDK
Rust-DPDK
 

Similar a 【20211202_toranoana.deno#3】denoでFFI

レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる
レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れるレガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる
レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れるsairoutine
 
Unityでlinqを使おう
Unityでlinqを使おうUnityでlinqを使おう
Unityでlinqを使おうYuuki Takada
 
griffon plugin を 実際に作ってみよう #jggug
griffon plugin を 実際に作ってみよう #jgguggriffon plugin を 実際に作ってみよう #jggug
griffon plugin を 実際に作ってみよう #jggugkimukou_26 Kimukou
 
スタート低レイヤー #0
スタート低レイヤー #0スタート低レイヤー #0
スタート低レイヤー #0Kiwamu Okabe
 
ニコニコを支える Erlang / Elixir
ニコニコを支える Erlang / Elixirニコニコを支える Erlang / Elixir
ニコニコを支える Erlang / Elixirkojingharang
 
Newcomer2020 Docker研修
Newcomer2020 Docker研修Newcomer2020 Docker研修
Newcomer2020 Docker研修Suguru Yazawa
 
「AROW」お披露目(実用編)
「AROW」お披露目(実用編)「AROW」お披露目(実用編)
「AROW」お披露目(実用編)Drecom Co., Ltd.
 
Dockerを使ってみよう
Dockerを使ってみようDockerを使ってみよう
Dockerを使ってみようRyo Adachi
 
Unityネイティブプラグインマニアクス #denatechcon
Unityネイティブプラグインマニアクス #denatechconUnityネイティブプラグインマニアクス #denatechcon
Unityネイティブプラグインマニアクス #denatechconDeNA
 
Visual Studio Community 2013 で始めるプログラミング Win32/MFC #clrh93
Visual Studio Community 2013 で始めるプログラミング Win32/MFC #clrh93Visual Studio Community 2013 で始めるプログラミング Win32/MFC #clrh93
Visual Studio Community 2013 で始めるプログラミング Win32/MFC #clrh93hiyohiyo
 
The Art of Network Protocols - RIP編 -
The Art of Network Protocols - RIP編 -The Art of Network Protocols - RIP編 -
The Art of Network Protocols - RIP編 -kirin_gumi
 
Perl暦およそ10年(?)の僕がデータベースを使えるようになるまでの昔話
Perl暦およそ10年(?)の僕がデータベースを使えるようになるまでの昔話Perl暦およそ10年(?)の僕がデータベースを使えるようになるまでの昔話
Perl暦およそ10年(?)の僕がデータベースを使えるようになるまでの昔話azuma satoshi
 
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2tamtam180
 
Getting Started GraalVM (再アップロード)
Getting Started GraalVM (再アップロード)Getting Started GraalVM (再アップロード)
Getting Started GraalVM (再アップロード)tamtam180
 
XenServerによるお手軽開発サーバ運用
XenServerによるお手軽開発サーバ運用XenServerによるお手軽開発サーバ運用
XenServerによるお手軽開発サーバ運用Shinya Okano
 
20170527 inside .NET Core on Linux
20170527 inside .NET Core on Linux20170527 inside .NET Core on Linux
20170527 inside .NET Core on LinuxTakayoshi Tanaka
 
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行gree_tech
 
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラーNode.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラーmganeko
 
【学習メモ#1st】12ステップで作る組込みOS自作入門
【学習メモ#1st】12ステップで作る組込みOS自作入門【学習メモ#1st】12ステップで作る組込みOS自作入門
【学習メモ#1st】12ステップで作る組込みOS自作入門sandai
 

Similar a 【20211202_toranoana.deno#3】denoでFFI (20)

レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる
レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れるレガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる
レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる
 
Unityでlinqを使おう
Unityでlinqを使おうUnityでlinqを使おう
Unityでlinqを使おう
 
griffon plugin を 実際に作ってみよう #jggug
griffon plugin を 実際に作ってみよう #jgguggriffon plugin を 実際に作ってみよう #jggug
griffon plugin を 実際に作ってみよう #jggug
 
スタート低レイヤー #0
スタート低レイヤー #0スタート低レイヤー #0
スタート低レイヤー #0
 
ニコニコを支える Erlang / Elixir
ニコニコを支える Erlang / Elixirニコニコを支える Erlang / Elixir
ニコニコを支える Erlang / Elixir
 
Newcomer2020 Docker研修
Newcomer2020 Docker研修Newcomer2020 Docker研修
Newcomer2020 Docker研修
 
「AROW」お披露目(実用編)
「AROW」お披露目(実用編)「AROW」お披露目(実用編)
「AROW」お披露目(実用編)
 
Dockerを使ってみよう
Dockerを使ってみようDockerを使ってみよう
Dockerを使ってみよう
 
Unityネイティブプラグインマニアクス #denatechcon
Unityネイティブプラグインマニアクス #denatechconUnityネイティブプラグインマニアクス #denatechcon
Unityネイティブプラグインマニアクス #denatechcon
 
Visual Studio Community 2013 で始めるプログラミング Win32/MFC #clrh93
Visual Studio Community 2013 で始めるプログラミング Win32/MFC #clrh93Visual Studio Community 2013 で始めるプログラミング Win32/MFC #clrh93
Visual Studio Community 2013 で始めるプログラミング Win32/MFC #clrh93
 
The Art of Network Protocols - RIP編 -
The Art of Network Protocols - RIP編 -The Art of Network Protocols - RIP編 -
The Art of Network Protocols - RIP編 -
 
Perl暦およそ10年(?)の僕がデータベースを使えるようになるまでの昔話
Perl暦およそ10年(?)の僕がデータベースを使えるようになるまでの昔話Perl暦およそ10年(?)の僕がデータベースを使えるようになるまでの昔話
Perl暦およそ10年(?)の僕がデータベースを使えるようになるまでの昔話
 
Dll Injection
Dll InjectionDll Injection
Dll Injection
 
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
 
Getting Started GraalVM (再アップロード)
Getting Started GraalVM (再アップロード)Getting Started GraalVM (再アップロード)
Getting Started GraalVM (再アップロード)
 
XenServerによるお手軽開発サーバ運用
XenServerによるお手軽開発サーバ運用XenServerによるお手軽開発サーバ運用
XenServerによるお手軽開発サーバ運用
 
20170527 inside .NET Core on Linux
20170527 inside .NET Core on Linux20170527 inside .NET Core on Linux
20170527 inside .NET Core on Linux
 
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
 
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラーNode.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
 
【学習メモ#1st】12ステップで作る組込みOS自作入門
【学習メモ#1st】12ステップで作る組込みOS自作入門【学習メモ#1st】12ステップで作る組込みOS自作入門
【学習メモ#1st】12ステップで作る組込みOS自作入門
 

Más de 虎の穴 開発室

Railsのデバッグ どうやるかを改めて確認する
Railsのデバッグ どうやるかを改めて確認するRailsのデバッグ どうやるかを改めて確認する
Railsのデバッグ どうやるかを改めて確認する虎の穴 開発室
 
虎の穴ラボ エンジニア採用説明資料 .pdf
虎の穴ラボ エンジニア採用説明資料 .pdf虎の穴ラボ エンジニア採用説明資料 .pdf
虎の穴ラボ エンジニア採用説明資料 .pdf虎の穴 開発室
 
Deno Deployと組み合わせるのに Upstashをおすすめしたい.pdf
Deno Deployと組み合わせるのに Upstashをおすすめしたい.pdfDeno Deployと組み合わせるのに Upstashをおすすめしたい.pdf
Deno Deployと組み合わせるのに Upstashをおすすめしたい.pdf虎の穴 開発室
 
toranoana.deno #6 アジェンダ 採用説明
toranoana.deno #6 アジェンダ 採用説明toranoana.deno #6 アジェンダ 採用説明
toranoana.deno #6 アジェンダ 採用説明虎の穴 開発室
 
Deno 向け WEB 開発用のツールを作ったので 紹介します
Deno 向け WEB 開発用のツールを作ったので 紹介しますDeno 向け WEB 開発用のツールを作ったので 紹介します
Deno 向け WEB 開発用のツールを作ったので 紹介します虎の穴 開発室
 
Supabase Edge Functions と Netlify Edge Functions を使ってみる – 機能とその比較 –
Supabase Edge Functions と Netlify Edge Functions を使ってみる – 機能とその比較 –Supabase Edge Functions と Netlify Edge Functions を使ってみる – 機能とその比較 –
Supabase Edge Functions と Netlify Edge Functions を使ってみる – 機能とその比較 –虎の穴 開発室
 
【エンジニアの勉強法ハックLT- vol.7】ゲームから学んだ勉強のこと
【エンジニアの勉強法ハックLT- vol.7】ゲームから学んだ勉強のこと【エンジニアの勉強法ハックLT- vol.7】ゲームから学んだ勉強のこと
【エンジニアの勉強法ハックLT- vol.7】ゲームから学んだ勉強のこと虎の穴 開発室
 
通販開発部の西田さん「通販開発マネジメントの5ルール」
通販開発部の西田さん「通販開発マネジメントの5ルール」通販開発部の西田さん「通販開発マネジメントの5ルール」
通販開発部の西田さん「通販開発マネジメントの5ルール」虎の穴 開発室
 
社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!
社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!
社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!虎の穴 開発室
 
セキュリティを強化しよう!CloudArmorの機能解説
セキュリティを強化しよう!CloudArmorの機能解説セキュリティを強化しよう!CloudArmorの機能解説
セキュリティを強化しよう!CloudArmorの機能解説虎の穴 開発室
 
JavaScript LT会 〜 React.js Node.js歓迎 〜 Deno で やってみるweb開発
JavaScript LT会 〜 React.js   Node.js歓迎 〜 Deno で やってみるweb開発JavaScript LT会 〜 React.js   Node.js歓迎 〜 Deno で やってみるweb開発
JavaScript LT会 〜 React.js Node.js歓迎 〜 Deno で やってみるweb開発虎の穴 開発室
 
Amplify Studioを使ってみた
Amplify Studioを使ってみたAmplify Studioを使ってみた
Amplify Studioを使ってみた虎の穴 開発室
 
いいテスト会 (スプリントレビュー) をやろう!
いいテスト会 (スプリントレビュー) をやろう!いいテスト会 (スプリントレビュー) をやろう!
いいテスト会 (スプリントレビュー) をやろう!虎の穴 開発室
 
【Saitama.js】Denoのすすめ
【Saitama.js】Denoのすすめ【Saitama.js】Denoのすすめ
【Saitama.js】Denoのすすめ虎の穴 開発室
 
虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について
虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について
虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について虎の穴 開発室
 
虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント
虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント 虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント
虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント 虎の穴 開発室
 
【20220120 toranoana.deno#4】deno を使って「ログイン」するサービスを作る
【20220120 toranoana.deno#4】deno を使って「ログイン」するサービスを作る【20220120 toranoana.deno#4】deno を使って「ログイン」するサービスを作る
【20220120 toranoana.deno#4】deno を使って「ログイン」するサービスを作る虎の穴 開発室
 
虎の穴ラボ エンジニア採用説明資料
虎の穴ラボ エンジニア採用説明資料 虎の穴ラボ エンジニア採用説明資料
虎の穴ラボ エンジニア採用説明資料 虎の穴 開発室
 

Más de 虎の穴 開発室 (20)

FizzBuzzで学ぶJavaの進化
FizzBuzzで学ぶJavaの進化FizzBuzzで学ぶJavaの進化
FizzBuzzで学ぶJavaの進化
 
Railsのデバッグ どうやるかを改めて確認する
Railsのデバッグ どうやるかを改めて確認するRailsのデバッグ どうやるかを改めて確認する
Railsのデバッグ どうやるかを改めて確認する
 
虎の穴ラボ エンジニア採用説明資料 .pdf
虎の穴ラボ エンジニア採用説明資料 .pdf虎の穴ラボ エンジニア採用説明資料 .pdf
虎の穴ラボ エンジニア採用説明資料 .pdf
 
Deno Deployと組み合わせるのに Upstashをおすすめしたい.pdf
Deno Deployと組み合わせるのに Upstashをおすすめしたい.pdfDeno Deployと組み合わせるのに Upstashをおすすめしたい.pdf
Deno Deployと組み合わせるのに Upstashをおすすめしたい.pdf
 
toranoana.deno #6 アジェンダ 採用説明
toranoana.deno #6 アジェンダ 採用説明toranoana.deno #6 アジェンダ 採用説明
toranoana.deno #6 アジェンダ 採用説明
 
Deno 向け WEB 開発用のツールを作ったので 紹介します
Deno 向け WEB 開発用のツールを作ったので 紹介しますDeno 向け WEB 開発用のツールを作ったので 紹介します
Deno 向け WEB 開発用のツールを作ったので 紹介します
 
Supabase Edge Functions と Netlify Edge Functions を使ってみる – 機能とその比較 –
Supabase Edge Functions と Netlify Edge Functions を使ってみる – 機能とその比較 –Supabase Edge Functions と Netlify Edge Functions を使ってみる – 機能とその比較 –
Supabase Edge Functions と Netlify Edge Functions を使ってみる – 機能とその比較 –
 
GCPの画像認識APIの紹介
GCPの画像認識APIの紹介 GCPの画像認識APIの紹介
GCPの画像認識APIの紹介
 
【エンジニアの勉強法ハックLT- vol.7】ゲームから学んだ勉強のこと
【エンジニアの勉強法ハックLT- vol.7】ゲームから学んだ勉強のこと【エンジニアの勉強法ハックLT- vol.7】ゲームから学んだ勉強のこと
【エンジニアの勉強法ハックLT- vol.7】ゲームから学んだ勉強のこと
 
通販開発部の西田さん「通販開発マネジメントの5ルール」
通販開発部の西田さん「通販開発マネジメントの5ルール」通販開発部の西田さん「通販開発マネジメントの5ルール」
通販開発部の西田さん「通販開発マネジメントの5ルール」
 
社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!
社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!
社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!
 
セキュリティを強化しよう!CloudArmorの機能解説
セキュリティを強化しよう!CloudArmorの機能解説セキュリティを強化しよう!CloudArmorの機能解説
セキュリティを強化しよう!CloudArmorの機能解説
 
JavaScript LT会 〜 React.js Node.js歓迎 〜 Deno で やってみるweb開発
JavaScript LT会 〜 React.js   Node.js歓迎 〜 Deno で やってみるweb開発JavaScript LT会 〜 React.js   Node.js歓迎 〜 Deno で やってみるweb開発
JavaScript LT会 〜 React.js Node.js歓迎 〜 Deno で やってみるweb開発
 
Amplify Studioを使ってみた
Amplify Studioを使ってみたAmplify Studioを使ってみた
Amplify Studioを使ってみた
 
いいテスト会 (スプリントレビュー) をやろう!
いいテスト会 (スプリントレビュー) をやろう!いいテスト会 (スプリントレビュー) をやろう!
いいテスト会 (スプリントレビュー) をやろう!
 
【Saitama.js】Denoのすすめ
【Saitama.js】Denoのすすめ【Saitama.js】Denoのすすめ
【Saitama.js】Denoのすすめ
 
虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について
虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について
虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について
 
虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント
虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント 虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント
虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント
 
【20220120 toranoana.deno#4】deno を使って「ログイン」するサービスを作る
【20220120 toranoana.deno#4】deno を使って「ログイン」するサービスを作る【20220120 toranoana.deno#4】deno を使って「ログイン」するサービスを作る
【20220120 toranoana.deno#4】deno を使って「ログイン」するサービスを作る
 
虎の穴ラボ エンジニア採用説明資料
虎の穴ラボ エンジニア採用説明資料 虎の穴ラボ エンジニア採用説明資料
虎の穴ラボ エンジニア採用説明資料
 

【20211202_toranoana.deno#3】denoでFFI

  • 1. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. denoでFFI
 
 虎の穴ラボ 藤原 佳顕
 1
  • 2. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. アジェンダ
 ● 概要 ● やりたかったこと ● ソースを見てみよう ● 作ってみよう 2
  • 3. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. 自己紹介
 3 ● 名前
 ○ 藤原佳顕(@nuhera, @zonuko)
 ● 仕事
 ○ FantiaとかCreatiaとか社内アプリとか
 ● 好み
 ○ Clojure、Rust
 ● 趣味
 ○ 格闘ゲーム
 ■ Melty Blood、Guilty Gear
 ○ STG(ダライアスとか)も好き
 ○ 最近は女神転生Vずっとやってました

  • 4. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. 概要
 4 ● deno1.13あたりからFFI機能が追加されています 
 ○ what’s ffi?
 ■ 別の言語で作られた関すなどをまた別の言語から呼び出せる機能 
 ■ deno固有の言葉ではない
 ○ これによってDLLやSOファイルなど、いわゆるダイナミック/スタティックライブラリを Denoから呼び出せるように

  • 5. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. 概要
 5 ● 代表的なライブラリ
 ○ と言われて何が思い浮かびますか? 
 ○ libmysqlclient.so
 ○ RTP
 ■ RPGツクールのランタイムライブラリ群 
 ○ Win32 DLL (kernel32.dll、user32.dll、gdi32.dllなど) 

  • 6. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. やりたかったこと
 ● DenoにFFIが入ったということはlibmysqlclient経由でmysql接続できるのでは?
 ● mysqlの接続方法自体はいくつかある
 ○ TCP接続
 ○ Unix Domain Socket接続
 ○ 名前付きパイプ
 ■ プロセス間通信で一般的に使われるやつ
 
 
 6
  • 7. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. やりたかったこと
 ● とはいえDenoにはmysql用のライブラリがすでにある
 ○ https://deno.land/x/mysql@v2.10.1
 
 
 7 private async _connect() { // TODO: implement connect timeout const { hostname, port = 3306, socketPath, username = "", password } = this.config; log.info(`connecting ${this.remoteAddr}`); this.conn = !socketPath ? await Deno.connect({ transport: "tcp", hostname, port, }) : await Deno.connect({ transport: "unix", path: socketPath, } as any); … mysqlがインストールされているかに関わらず、tcp/ドメイ ンソケット経由なのがわかる
 

  • 8. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. やりたかったこと
 
 ● ではDenoでのFFIするときにインターフェースはどうなっているか
 ○ ソースはこんな感じ
 
 
 
 
 
 ● 対応している型はchar / signed char, unsigned char, short int, unsigned short int, int / signed int, unsigned int, long long int, unsigned long long int, size_t, float, double, void, const uint8_t *
 ○ https://deno.land/manual@main/runtime/ffi_api
 
 8 const libName = `./libadd.${libSuffix}`; // Open library and define exported symbols const dylib = Deno.dlopen(libName, { "add": { parameters: ["isize", "isize"], result: "isize" }, });
  • 9. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. やりたかったこと
 
 ● 一方でlibmysql側のインターフェースは? 
 ○ 例:コネクション貼りたい場合
 ■ https://dev.mysql.com/doc/refman/5.6/ja/mysql-real-connect.html 
 ■ MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag) ■ MYSQL構造体が出てきているので現段階ではうまく扱えなさそう 
 ● →とりあえず他の言語でどうやっているか見てみよう 
 9
  • 10. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. ソースを見てみよう
 ● mysqlといえばRails
 ○ https://github.com/brianmario/mysql2
 ● Rubyには拡張ライブラリという仕組みがあります
 ○ https://docs.ruby-lang.org/en/2.4.0/extension_ja_rdoc.html
 ○ ルール基づいて作られたCライブラリをRuby側から一本のクラスやモジュールであるかのように呼び出せる
 ○ 抜粋
 ■ rb_define_module:新しいモジュール定義
 ■ rb_define_class_under: あるクラスを継承したクラスをモジュール配下に定義
 ■ rb_define_method:クラスにメソッドを定義
 ■ rb_define_private_method: クラスにプライベートメソッドを定義
 ○ Ruby側でどこからともなくconnectionメソッドが呼ばれているので、rb_define_method、rb_define_private_methodあたりで検 索かければなにかでてくるのでは?
 10
  • 11. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. ソースを見てみよう
 ● https://github.com/brianmario/mysql2/blob/6652da20010ddfbbe6bceb8e41666d05e512346c/ext/mysql2/client.c#L445
 ● 最終的な部分
 11 static void *nogvl_connect(void *ptr) { struct nogvl_connect_args *args = ptr; MYSQL *client; client = mysql_real_connect(args->mysql, args->host, args->user, args->passwd, args->db, args->port, args->unix_socket, args->client_flag); return (void *)(client ? Qtrue : Qfalse); } =>直接libmysqlclient.soとかを呼び出していることはなく、C言語等でラップされている 

  • 12. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. 作ってみよう
 ● まずはコネクション取得(C側)
 ○ mysql_init→mysql_real_connectとする必要があるのでどちらのラッパー関数も定義(ついでにcloseも)
 12 #include <mysql/mysql.h> #include <stdio.h> MYSQL *conn = NULL; void init() { conn = mysql_init(NULL); } int connect(const char *host, const char *user, const char *passwd, const char *db_name, int port) { if (!mysql_real_connect(conn, host, user, passwd, db_name, port, NULL, 0)) { fprintf(stderr, "Failed to connect to database: Error: %sn", mysql_error(conn)); fflush(stderr); return 0; } return 1; } void close(void) { mysql_close(conn); }
  • 13. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. 作ってみよう
 ● ネクション取得(deno側)
 13 const C_TERMINAL_SYMBOL = "0"; const MYSQL_HOST = "localhost"; const MYSQL_USER = "root"; const MYSQL_PASSWD = ""; const MYSQL_DB_NAME = "mysql"; const MYSQL_PORT = 3306; function strToBytes(word: string): Uint8Array { return new TextEncoder().encode(`${word}${C_TERMINAL_SYMBOL}`); } function ffiSuffix(): string { switch (Deno.build.os) { case "windows": return "dll"; case "darwin": return "dylib"; case "linux": return "so"; } } interface LibInterfaces extends Record<string, Deno.ForeignFunction> { init: Deno.ForeignFunction; connect: Deno.ForeignFunction; close: Deno.ForeignFunction; } const libInterfaces: LibInterfaces = { init: { parameters: [], result: "void" }, connect: { parameters: ["buffer", "buffer", "buffer", "buffer", "i32"], result: "i32", }, close: { parameters: [], result: "void" }, };
  • 14. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. 作ってみよう
 ● コネクション取得続き(deno側)
 14 class MySQL { #dylib: Deno.DynamicLibrary<LibInterfaces> | null = null; readonly host = strToBytes(MYSQL_HOST); readonly user = strToBytes(MYSQL_USER); readonly passwd = strToBytes(MYSQL_PASSWD); readonly dbName = strToBytes(MYSQL_DB_NAME); private isConn = false; constructor() { const libName = `./ext/mysql/mysql.${ffiSuffix()}`; this.#dylib = Deno.dlopen(libName, libInterfaces); this.#dylib.symbols.init(); const res = this.#dylib.symbols.connect(this.host, this.user, this.passwd, this.dbName, MYSQL_PORT); if (res === 0) { this.close(); throw new Error("コネクション確立に失敗しました。 "); } this.isConn = true; } close() { if (!this.#dylib) { return; } if (this.isConn) { this.#dylib.symbols.close(); this.#dylib.close(); this.#dylib = null; } } } const client = new MySQL(); client.close();
  • 15. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. 作ってみよう
 ● 動かしてみる
 ○ libmysqlclient.(so|dll|dylib)のフォルダを指定してコンパイルする必要がある
 ○ 今回はコネクション貼って即時クローズするので、例外がでなければとりあえずOK
 15 > gcc -c -fPIC -o ./ext/mysql/mysql.o ./ext/mysql/mysql.c > gcc -shared -W -o ./ext/mysql/mysql.so ./ext/mysql/mysql.o -L/usr/lib/x86_64-linux-gnu -lmysqlclient > deno run --unstable --allow-ffi mod.ts (macの場合はlibフォルダが異なるので -L/usr/local/lib などとする)

  • 16. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. 課題とハマったところ
 ● たまに接続文字列の後ろにゴミがくっついてエラーになる(“127.0.0.1L”とか)
 ○ bufferに文字列食わせるときに終端文字が必要だった(0)
 ○ C言語で文字列扱う場合は必要な処理だがDeno側に必要なのは盲点だった
 ● queryの結果取得が面倒
 ○ mysql_real_query→mysql_use_resultで結果取得といった流れ
 ○ mysql_use_resultの戻り値がMYSQL_RES構造体なのでこれもそのままは扱えない
 ○ また、まだbufferを戻り値にできない→クエリ実行結果を文字列としては戻せない
 ● そもそもRustでlibmysqlclientをラップしたほうが楽では?
 ○ こちらであればdeno_bindgenが使える
 ○ https://deno.land/manual@v1.16.3/runtime/ffi_api
 16
  • 17. Copyright  (C) 2021 Toranoana Inc. All Rights Reserved. まとめ
 ● そのままでは複雑な構造体をI/Fとして持つものをFFIすることは難しそう 
 ● CやC++でさらに使いたいdllやsoファイルをラップする必要がありそう 
 ○ Cのグローバルにconnectionとか置かないとダメそう 
 ■ Cの中だけに収まってくれるか?という勝負 
 ● ただし、やり方さえ確立できればどんなものでもFFIできそう 
 ● より細かい話は12/4に公開するアドベントカレンダーのブログで紹介しています。 
 17