C言語からC++/Rust/Python/Go/Java言語の関数呼び出しを教えて!
こういった悩みにお答えします.
本記事の信頼性
- リアルタイムシステムの研究歴12年.
- 東大教員の時に,英語でOS(Linuxカーネル)の授業.
- 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校(UNC)コンピュータサイエンス学部で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発.
- プログラミング歴15年以上,習得している言語: C/C++,Python,Solidity/Vyper,Java,Ruby,Go,Rust,D,HTML/CSS/JS/PHP,MATLAB,Verse(UEFN), Assembler (x64,aarch64).
- 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」をGitHubにオープンソースとして公開.
- 2020年1月~現在はアメリカのノースカロライナ州チャペルヒルにあるGuarantee Happiness LLCのCTOとしてECサイト開発やWeb/SNSマーケティングの業務.2022年6月~現在はアメリカのノースカロライナ州チャペルヒルにあるJapanese Tar Heel, Inc.のCEO兼CTO.
- 最近は自然言語処理AIとイーサリアムに関する有益な情報発信に従事.
- (AI全般を含む)自然言語処理AIの論文の日本語訳や,AIチャットボット(ChatGPT,Auto-GPT,Gemini(旧Bard)など)の記事を50本以上執筆.アメリカのサンフランシスコ(広義のシリコンバレー)の会社でプロンプトエンジニア・マネージャー・Quality Assurance(QA)の業務委託の経験あり.
- (スマートコントラクトのプログラミングを含む)イーサリアムや仮想通貨全般の記事を200本以上執筆.イギリスのロンドンの会社で仮想通貨の英語の記事を日本語に翻訳する業務委託の経験あり.
こういった私から学べます.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!
C言語だと実装するのに面倒なことがありますよね.
そんなあなたにC言語からC++/Rust/Python/Go/Java言語の関数呼び出しを紹介します.
C言語と他のプログラミング言語の両方のメリットを活かしましょう!
目次
C言語からC++/Rust/Python/Go/Java言語の関数呼び出し
C言語からC++/Rust/Python/Go/Java言語の関数呼び出しを紹介します.
C言語のコードは以下になります.
「Hello World!」を表示するprint_hello関数を呼び出していますが,C言語のコードには定義がありません.
他のプログラミング言語のコードでprint_hello関数を定義して呼び出します.
1 2 3 4 5 6 7 8 9 10 11 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ void print_hello(void); int main(void) { print_hello(); return 0; } |
extern "C":C言語からC++言語の関数呼び出し
C言語からC++言語の関数呼び出しには,「extern "C"」宣言を利用します.
C++言語のコードは以下になります.
1 2 3 4 5 6 7 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <iostream> extern "C" void print_hello(void) { std::cout << "Hello World!" << std::endl; } |
実行結果は以下になります.
1 2 3 4 5 |
$ g++ -c hello.cpp $ gcc -c c2other.c $ g++ c2other.o hello.o $ a.out Hello World! |
no_mangle,extern "C":C言語からRust言語の関数呼び出し
C言語からRust言語の関数呼び出しには,「#[no_mangle]」と「extern "C"」を利用します.
※「extern "C"」はC++言語と同じですね.
Rust言語のコードは以下になります.
1 2 3 4 5 6 7 8 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #[no_mangle] pub extern "C" fn print_hello() { println!("Hello World!"); } |
実行結果は以下になります.
1 2 3 4 5 |
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. $ rustc --crate-type="dylib" hello.rs $ gcc c2other.c -L. -lhello $ a.out Hello World! |
CPython:C言語からPython言語の関数呼び出し
C言語からPython言語の関数呼び出しには,「CPython」を利用します.
CPythonでは,C言語でPython言語固有の呼び出しが必要になります.
C言語とPython言語のコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #define PY_SSIZE_T_CLEAN #include <Python.h> #define MODULE_NAME "hello" #define FUNC_NAME "print_hello" int main(void) { PyObject *pName, *pModule, *pFunc; Py_Initialize(); pName = PyUnicode_DecodeFSDefault(MODULE_NAME); pModule = PyImport_Import(pName); Py_DECREF(pName); if (pModule != NULL) { pFunc = PyObject_GetAttrString(pModule, FUNC_NAME); if (pFunc != NULL && PyCallable_Check(pFunc)) { PyObject_CallObject(pFunc, NULL); Py_DECREF(pFunc); } } Py_DECREF(pModule); Py_Finalize(); return 0; } |
1 2 3 4 5 6 7 8 |
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # Author: Hiroyuki Chishiro # License: 2-Clause BSD # def print_hello(): print("Hello World!") |
実行結果は以下になります.
※必要に応じてPythonのバージョンを変更して下さい.
1 2 3 4 |
$ export PYTHONPATH=$PYTHONPATH:. $ gcc cpython.c -I/usr/include/python3.10 -lpython3.10 $ a.out Hello World! |
参考までに,以下のコードのようにPython言語のprint関数をC言語のコードに埋め込むことも可能です.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #define PY_SSIZE_T_CLEAN #include <Python.h> int main(void) { Py_Initialize(); PyRun_SimpleString("print('Hello World!')"); Py_Finalize(); return 0; } |
実行結果は以下になります.
※必要に応じてPythonのバージョンを変更して下さい.
1 2 3 |
$ gcc cpython2.c -I/usr/include/python3.10/ -lpython3.10 $ a.out Hello World! |
c-shared:C言語からGo言語の関数呼び出し
C言語からGo言語の関数呼び出しにはビルドモードの「c-shared」を利用します.
Go言語のコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ package main import ( "C" "fmt" ) //export print_hello func print_hello() { fmt.Println("Hello World!") } func main() {} |
実行結果は以下になります.
1 2 3 4 5 |
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. $ go build -buildmode=c-shared -o hello.so hello.go $ gcc c2other.c hello.so $ a.out Hello World! |
JNI:C言語からJava言語の関数呼び出し
C言語からJava言語の関数呼び出しには,「Java Native Method(JNI)」を利用します.
JNIでは,C言語でJava言語固有の呼び出しが必要になります.
C言語とJava言語のコードは以下になります.
※必要に応じてJNIのバージョンを変更して下さい.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <jni.h> #include <stdio.h> #include <stdlib.h> #define CLASS_NAME "Hello" #define METHOD_NAME "print_hello" int main(void) { JNIEnv *env; JavaVM *jvm; int res; jclass cls; jmethodID mid; JavaVMOption options[1]; JavaVMInitArgs vm_args; options[0].optionString = "-Djava.class.path=."; vm_args.version = JNI_VERSION_1_8; vm_args.options = options; vm_args.nOptions = 1; if ((res = JNI_CreateJavaVM(&jvm, (void **) &env, &vm_args)) < 0) { fprintf(stderr, "Error: JNI_CreateJavaVM()\n"); exit(1); } if ((cls = (*env)->FindClass(env, CLASS_NAME)) == 0) { fprintf(stderr, "Error: cannot Find %s class.\n", CLASS_NAME); exit(2); } if ((mid = (*env)->GetStaticMethodID(env, cls, "print_hello", "()V")) == 0) { fprintf(stderr, "Error: cannot find %s method.\n", METHOD_NAME); exit(3); } (*env)->CallStaticVoidMethod(env, cls, mid, NULL); (*jvm)->DestroyJavaVM(jvm); return 0; } |
1 2 3 4 5 6 7 8 9 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ public class Hello { public static void print_hello() { System.out.println("Hello World!"); } } |
実行結果は以下になります.
※必要に応じてJDKのパスを変更して下さい.
1 2 3 4 5 |
$ javac Hello.java $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/jvm/java-1.11.0-openjdk-amd64/lib/server $ gcc -I/usr/lib/jvm/java-1.11.0-openjdk-amd64/include -I/usr/lib/jvm/java-1.11.0-openjdk-amd64/include/linux jni.c -L/usr/lib/jvm/java-1.11.0-openjdk-amd64/lib/server -ljvm $ a.out Hello World! |
参考:C言語からハードウェア記述言語(HDL:Hardware Description Language)への変換
C言語から他の言語の関数呼び出しと似たような手法としてC言語からハードウェア記述言語(HDL:Hardware Description Language)への変換があります.
いわゆるC to HDLと呼ばれる手法です.
C to HDLを利用することで,C言語からVerilogやVHDL等のHDLに変換することで開発コストを削減できます.
代表的なC to HDLのツールは以下になります.
- SystemC:C++言語ライクなHDL.
- Impulse C/CoDeveloper:C言語のサブセットとC言語互換の関数ライブラリを組み合わせたもので,特にFPGAデバイスをターゲットにしたアプリケーションのプログラミングをサポートするライブラリとツールチェーン.
まとめ
C言語からC++/Rust/Python/Go/Java言語の関数呼び出しを紹介しました.
C言語と他のプログラミング言語を連携する時の参考にして下さい.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!