PythonからC / C ++を呼び出しますか?[閉まっている]

538
shoosh 2008-09-28 19:34.

CまたはC ++ライブラリへのPythonバインディングを構築する最も簡単な方法は何でしょうか?

(これが問題になる場合は、Windowsを使用しています。)

12 answers

179
Ralph 2008-09-28 21:51.

あなたは見ている必要がありBoost.Pythonを。これが彼らのウェブサイトから取られた短い紹介です:

Boost Python Libraryは、PythonとC ++をインターフェースするためのフレームワークです。これにより、特別なツールを使用せずに、C ++コンパイラだけを使用して、C ++クラスの関数とオブジェクトをPythonに、またはその逆にすばやくシームレスに公開できます。これは、C ++インターフェイスを非侵入的にラップするように設計されているため、ラップするためにC ++コードをまったく変更する必要がないため、Boost.PythonはサードパーティのライブラリをPythonに公開するのに理想的です。ライブラリで高度なメタプログラミング手法を使用すると、ユーザーの構文が単純化されるため、ラッピングコードは一種の宣言型インターフェイス定義言語(IDL)のように見えます。

684
Florian Bösch 2008-09-29 00:53.

ctypesモジュールは標準ライブラリの一部であるため、常に問題が発生する傾向があったswigよりも安定しており、広く利用できます。

ctypesを使用する場合、Pythonに対するコンパイル時の依存関係を満たす必要があります。バインディングは、コンパイル対象のPythonだけでなく、ctypesを持つすべてのPythonで機能します。

foo.cppというファイルに話したい単純なC ++サンプルクラスがあるとします。

#include <iostream>

class Foo{
    public:
        void bar(){
            std::cout << "Hello" << std::endl;
        }
};

ctypesはC関数としか通信できないため、それらをextern "C"として宣言する関数を提供する必要があります。

extern "C" {
    Foo* Foo_new(){ return new Foo(); }
    void Foo_bar(Foo* foo){ foo->bar(); }
}

次に、これを共有ライブラリにコンパイルする必要があります

g++ -c -fPIC foo.cpp -o foo.o
g++ -shared -Wl,-soname,libfoo.so -o libfoo.so  foo.o

そして最後に、Pythonラッパーを作成する必要があります(例:fooWrapper.py)

from ctypes import cdll
lib = cdll.LoadLibrary('./libfoo.so')

class Foo(object):
    def __init__(self):
        self.obj = lib.Foo_new()

    def bar(self):
        lib.Foo_bar(self.obj)

あなたがそれを持ったらあなたはそれを次のように呼ぶことができます

f = Foo()
f.bar() #and you will see "Hello" on the screen
59
Ben Hoffstein 2008-09-28 19:44.

これを行う最も簡単な方法は、SWIGを使用することです。

SWIGチュートリアルの例:

/* File : example.c */
int fact(int n) {
    if (n <= 1) return 1;
    else return n*fact(n-1);
}

インターフェイスファイル:

/* example.i */
%module example
%{
/* Put header files here or function declarations like below */
extern int fact(int n);
%}

extern int fact(int n);

UnixでのPythonモジュールの構築:

swig -python example.i
gcc -fPIC -c example.c example_wrap.c -I/usr/local/include/python2.7
gcc -shared example.o example_wrap.o -o _example.so

使用法:

>>> import example
>>> example.fact(5)
120

python-devが必要であることに注意してください。また、一部のシステムでは、インストール方法に基づいて、Pythonヘッダーファイルが/usr/include/python2.7にあります。

チュートリアルから:

SWIGは、ほぼすべての言語機能をサポートする、かなり完全なC ++コンパイラです。これには、前処理、ポインター、クラス、継承、さらにはC ++テンプレートが含まれます。SWIGを使用して、構造とクラスをターゲット言語のプロキシクラスにパッケージ化することもできます。これにより、基盤となる機能が非常に自然な方法で公開されます。

50
Antonello 2014-05-26 22:30.

高水準データ型(多次元STLベクトルとPythonリスト)をリンクすることを目的として、このページからPython <-> C ++バインディングの旅を始めました:-)

ctypesとboost.pythonの両方に基づくソリューションを試しましたが(ソフトウェアエンジニアではありません)、高レベルのデータ型バインディングが必要な場合は複雑であることがわかりましたが、そのような場合はSWIGがはるかに単純であることがわかりました。

したがって、この例ではSWIGを使用しており、Linuxでテストされています(ただし、SWIGは利用可能であり、Windowsでも広く使用されています)。

目的は、2D STLベクトルの形式で行列を取り、各行の平均を(1D STLベクトルとして)返すC ++関数をPythonで使用できるようにすることです。

C ++のコード( "code.cpp")は次のとおりです。

#include <vector>
#include "code.h"

using namespace std;

vector<double> average (vector< vector<double> > i_matrix) {

  // Compute average of each row..
  vector <double> averages;
  for (int r = 0; r < i_matrix.size(); r++){
    double rsum = 0.0;
    double ncols= i_matrix[r].size();
    for (int c = 0; c< i_matrix[r].size(); c++){
      rsum += i_matrix[r][c];
    }
    averages.push_back(rsum/ncols);
  }
  return averages;
}

同等のヘッダー( "code.h")は次のとおりです。

#ifndef _code
#define _code

#include <vector>

std::vector<double> average (std::vector< std::vector<double> > i_matrix);

#endif

まず、C ++コードをコンパイルして、オブジェクトファイルを作成します。

g++ -c -fPIC code.cpp

次に、C ++関数のSWIGインターフェイス定義ファイル( "code.i")を定義します。

%module code
%{
#include "code.h"
%}
%include "std_vector.i"
namespace std {

  /* On a side note, the names VecDouble and VecVecdouble can be changed, but the order of first the inner vector matters! */
  %template(VecDouble) vector<double>;
  %template(VecVecdouble) vector< vector<double> >;
}

%include "code.h"

SWIGを使用して、SWIGインターフェイス定義ファイルからC ++インターフェイスのソースコードを生成します。

swig -c++ -python code.i

最後に、生成されたC ++インターフェイスソースファイルをコンパイルし、すべてをリンクして、Pythonで直接インポートできる共有ライブラリを生成します(「_」が重要です)。

g++ -c -fPIC code_wrap.cxx  -I/usr/include/python2.7 -I/usr/lib/python2.7
g++ -shared -Wl,-soname,_code.so -o _code.so code.o code_wrap.o

これで、Pythonスクリプトで関数を使用できるようになりました。

#!/usr/bin/env python

import code
a= [[3,5,7],[8,10,12]]
print a
b = code.average(a)
print "Assignment done"
print a
print b
43
Tom Wenseleers 2016-07-24 03:53.

ありますpybind11が、軽量版のようである、Boost.Python、すべての近代的なC ++コンパイラとの互換性:

https://pybind11.readthedocs.io/en/latest/

24
Wim Lavrijsen 2018-03-06 13:02.

最新のC ++の場合は、cppyyを使用します。 http://cppyy.readthedocs.io/en/latest/

これは、Clang / LLVMのC ++インタープリターであるClingに基づいています。バインディングは実行時に行われ、追加の中間言語は必要ありません。Clangのおかげで、C ++ 17をサポートしています。

pipを使用してインストールします。

    $ pip install cppyy

小さなプロジェクトの場合は、関心のある関連ライブラリとヘッダーをロードするだけです。たとえば、ctypesの例からコードを取得すると、このスレッドになりますが、ヘッダーセクションとコードセクションに分割されます。

    $ cat foo.h
    class Foo {
    public:
        void bar();
    };

    $ cat foo.cpp
    #include "foo.h"
    #include <iostream>

    void Foo::bar() { std::cout << "Hello" << std::endl; }

それをコンパイルします:

    $ g++ -c -fPIC foo.cpp -o foo.o
    $ g++ -shared -Wl,-soname,libfoo.so -o libfoo.so  foo.o

そしてそれを使用します:

    $ python
    >>> import cppyy
    >>> cppyy.include("foo.h")
    >>> cppyy.load_library("foo")
    >>> from cppyy.gbl import Foo
    >>> f = Foo()
    >>> f.bar()
    Hello
    >>>

大規模なプロジェクトは、準備されたリフレクション情報とそれらを作成するためのcmakeフラグメントの自動ロードでサポートされているため、インストールされたパッケージのユーザーは次の操作を簡単に実行できます。

    $ python
    >>> import cppyy
    >>> f = cppyy.gbl.Foo()
    >>> f.bar()
    Hello
    >>>

LLVMのおかげで、自動テンプレートインスタンス化などの高度な機能が可能です。例を続けるには:

    >>> v = cppyy.gbl.std.vector[cppyy.gbl.Foo]()
    >>> v.push_back(f)
    >>> len(v)
    1
    >>> v[0].bar()
    Hello
    >>>

注:私はcppyyの作者です。

13
mrgloom 2013-11-06 00:39.

Python用のcffiはオプションになると思います。

目標は、PythonからCコードを呼び出すことです。3番目の言語を学習しなくてもそうできるはずです。すべての選択肢では、独自の言語(Cython、SWIG)またはAPI(ctypes)を学習する必要があります。そのため、PythonとCを知っていることを前提とし、学習する必要のあるAPIの余分なビットを最小限に抑えようとしました。

http://cffi.readthedocs.org/en/release-0.7/

8
Jadav Bheda 2015-08-28 20:38.

問題は、私が正しく理解していれば、PythonからC関数を呼び出す方法です。次に、最善の策はCtypes(Pythonのすべてのバリアント間で移植可能なBTW)です。

>>> from ctypes import *
>>> libc = cdll.msvcrt
>>> print libc.time(None)
1438069008
>>> printf = libc.printf
>>> printf("Hello, %s\n", "World!")
Hello, World!
14
>>> printf("%d bottles of beer\n", 42)
42 bottles of beer
19

詳細なガイドについては、私のブログ記事を参照してください。

6
nicodjimenez 2015-12-30 07:27.

Javaラッパーを書くことを予期していない限り、Cythonは間違いなく進むべき道です。その場合、SWIGが望ましいかもしれません。

runcythonコマンドラインユーティリティを使用することをお勧めします。これにより、Cythonの使用プロセスが非常に簡単になります。構造化データをC ++に渡す必要がある場合は、Googleのprotobufライブラリをご覧ください。非常に便利です。

両方のツールを使用して作成した最小限の例を次に示します。

https://github.com/nicodjimenez/python2cpp

それが有用な出発点になることを願っています。

5
Yaroslav Nikitenko 2015-04-25 07:23.

まず、特定の目的を決定する必要があります。Pythonインタープリターの拡張と埋め込みに関する公式のPythonドキュメントについては前述しましたが、バイナリ拡張の概要を追加できます。ユースケースは、次の3つのカテゴリに分類できます。

  • アクセラレータモジュール:CPythonで実行される同等の純粋なPythonコードよりも高速に実行します。
  • ラッパーモジュール:既存のCインターフェースをPythonコードに公開します。
  • 低レベルのシステムアクセス:CPythonランタイム、オペレーティングシステム、または基盤となるハードウェアの低レベルの機能にアクセスします。

他の興味のある人にもっと広い視点を与えるために、そしてあなたの最初の質問は少し曖昧なので(「CまたはC ++ライブラリへ」)、この情報はあなたにとって興味深いかもしれないと思います。上記のリンクで、バイナリ拡張とその代替を使用することの欠点について読むことができます。

提案された他の回答とは別に、アクセラレータモジュールが必要な場合は、Numbaを試すことができます。これは、「インポート時、実行時、または静的に(付属のpyccツールを使用して)LLVMコンパイラインフラストラクチャを使用して最適化されたマシンコードを生成することによって」機能します。

pybind11の最小限の実行可能な例

pybind11は以前にで言及されました https://stackoverflow.com/a/38542539/895245 ただし、ここでは具体的な使用例と実装に関する詳細な説明を示します。

とにかく、pybind11は非常に使いやすいので、強くお勧めします。ヘッダーを含めるだけで、pybind11はテンプレートマジックを使用してPythonに公開するC ++クラスを検査し、それを透過的に実行します。

このテンプレートマジックの欠点は、コンパイルが遅くなり、pybind11を使用するファイルに数秒が追加されることです。たとえば、この問題で行われた調査を参照してください。PyTorchは同意します。この問題を修正する提案は次の場所で行われました。https://github.com/pybind/pybind11/pull/2445

これは、pybind11の素晴らしさを実感できる最小限の実行可能な例です。

class_test.cpp

#include <string>

#include <pybind11/pybind11.h>

struct ClassTest {
    ClassTest(const std::string &name) : name(name) { }
    void setName(const std::string &name_) { name = name_; }
    const std::string &getName() const { return name; }
    std::string name;
};

namespace py = pybind11;

PYBIND11_PLUGIN(class_test) {
    py::module m("my_module", "pybind11 example plugin");
    py::class_<ClassTest>(m, "ClassTest")
        .def(py::init<const std::string &>())
        .def("setName", &ClassTest::setName)
        .def("getName", &ClassTest::getName)
        .def_readwrite("name", &ClassTest::name);
    return m.ptr();
}

class_test_main.py

#!/usr/bin/env python3

import class_test

my_class_test = class_test.ClassTest("abc");
print(my_class_test.getName())
my_class_test.setName("012")
print(my_class_test.getName())
assert(my_class_test.getName() == my_class_test.name)

コンパイルして実行します。

#!/usr/bin/env bash
set -eux
g++ `python3-config --cflags` -shared -std=c++11 -fPIC class_test.cpp \
  -o class_test`python3-config --extension-suffix` `python3-config --libs`
./class_test_main.py

この例は、pybind11を使用してClassTestC ++クラスをPythonに簡単に公開できることを示しています。コンパイルは、名前のファイル作成し、自動的にの定義点として取り上げネイティブに定義されたモジュールを。class_test.cpython-36m-x86_64-linux-gnu.soclass_test_main.pyclass_test

おそらく、これがどれほど素晴らしいかという認識は、ネイティブPython APIを使用して同じことを手動で実行しようとした場合にのみ沈みます。たとえば、コードが約10倍多いこの例を参照してください。 https://github.com/cirosantilli/python-cheat/blob/4f676f62e87810582ad53b2fb426b74eae52aad5/py_from_c/pure.cその例では、CコードがPythonクラスに含まれるすべての情報(メンバー、メソッド、その他のメタデータなど)を使用して、Pythonクラスを少しずつ苦痛かつ明示的に定義する必要があることがわかります。参照:

  • python-C ++拡張機能はC ++オブジェクトを取得し、そのメンバー関数を呼び出すことができますか?
  • C ++クラスインスタンスをPython組み込みインタープリターに公開する
  • Python C拡張機能を備えたクラス(メソッドではない)の完全で最小限の例?
  • PythonをC ++に埋め込み、Boost.Pythonを使用してC ++コードからメソッドを呼び出す
  • Python C ++拡張機能の継承

pybind11は、でBoost.Python言及されたものと類似していると主張していますhttps://stackoverflow.com/a/145436/895245 しかし、Boostプロジェクト内にいるという肥大化から解放されるため、より最小限に抑えられます。

pybind11は、主に既存のC ++コードのPythonバインディングを作成するために、PythonでC ++タイプを公開する軽量のヘッダーのみのライブラリです。その目標と構文は、David Abrahamsによる優れたBoost.Pythonライブラリに似ています。コンパイル時のイントロスペクションを使用して型情報を推測することにより、従来の拡張モジュールの定型コードを最小限に抑えます。

Boost.Pythonの主な問題、およびそのような同様のプロジェクトを作成する理由は、Boostです。Boostは、存在するほぼすべてのC ++コンパイラで動作する、非常に大規模で複雑なユーティリティライブラリのスイートです。この互換性にはコストがかかります。最も古くてバグの多いコンパイラー標本をサポートするには、難解なテンプレートのトリックと回避策が必要です。C ++ 11互換のコンパイラが広く利用できるようになった今、この重い機械は非常に大きく、不必要な依存関係になっています。

このライブラリは、Boost.Pythonの小さな自己完結型バージョンであり、バインディングの生成に関係のないものはすべて削除されていると考えてください。コメントがない場合、コアヘッダーファイルは約4K行のコードのみを必要とし、Python(2.7または3.x、またはPyPy2.7> = 5.7)およびC ++標準ライブラリに依存します。このコンパクトな実装は、いくつかの新しいC ++ 11言語機能(具体的には、タプル、ラムダ関数、可変個引数テンプレート)のおかげで可能になりました。作成以来、このライブラリは多くの点でBoost.Pythonを超えて成長し、多くの一般的な状況で劇的に単純なバインディングコードにつながりました。

pybind11は、現在のMicrosoft PythonCバインディングドキュメントで強調されている唯一の非ネイティブの代替手段でもあります。 https://docs.microsoft.com/en-us/visualstudio/python/working-with-c-cpp-python-in-visual-studio?view=vs-2019(アーカイブ)。

Ubuntu 18.04、pybind11 2.0.1、Python 3.6.8、GCC7.4.0でテスト済み。

3
Garfield 2019-12-19 23:56.

私はcppyyが大好きです。これにより、PythonをC ++コードで非常に簡単に拡張でき、必要に応じてパフォーマンスが劇的に向上します。

それは強力で、率直に言って非常に使いやすいです、

これは、numpy配列を作成し、それをC ++のクラスメンバー関数に渡す方法の例です。

cppyy_test.py

import cppyy
import numpy as np
cppyy.include('Buffer.h')


s = cppyy.gbl.Buffer()
numpy_array = np.empty(32000, np.float64)
s.get_numpy_array(numpy_array.data, numpy_array.size)
print(numpy_array[:20])

Buffer.h

struct Buffer {
  void get_numpy_array(double *ad, int size) {
    for( long i=0; i < size; i++)
        ad[i]=i;
  }
};

Pythonモジュールを非常に簡単に(CMakeを使用して)作成することもできます。これにより、C ++コードを常に再コンパイルする必要がなくなります。

Related questions

MORE COOL STUFF

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは、夫に会ったとき、典型的な交際のアドバイスに逆らいました。

マイケルシーンが非営利の俳優である理由

マイケルシーンが非営利の俳優である理由

マイケルシーンは非営利の俳優ですが、それは正確にはどういう意味ですか?

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

特徴的なスターのコリン・エッグレスフィールドは、RomaDrama Liveでのスリル満点のファンとの出会いについて料理しました!加えて、大会での彼のINSPIREプログラム。

「たどりつけば」をオンラインでストリーミングできない理由

「たどりつけば」をオンラインでストリーミングできない理由

ノーザンエクスポージャーが90年代の最も人気のある番組の1つになった理由を確認するには、Blu-rayまたはDVDプレーヤーをほこりで払う必要があります。

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖は、世界で2番目に大きいボイリング湖です。そこにたどり着くまでのトレッキングは大変で長いですが、努力する価値は十分にあります。

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

サロンからのヘアトリミングや個人的な寄付は、油流出を吸収して環境を保護するのに役立つマットとして再利用できます。

ホワイトハウスの最も記憶に残る結婚式を見てください

ホワイトハウスの最も記憶に残る結婚式を見てください

過去200年以上の間にホワイトハウスで結婚したのはほんの数人です。彼らは誰でしたか、そしてそこで結婚式を獲得するために何が必要ですか?

ジェイ・ブルースはどうやら子供を妊娠することによってメッツから離れて取引されていることを祝った

ジェイ・ブルースはどうやら子供を妊娠することによってメッツから離れて取引されていることを祝った

あなたが一時的に会っていなかったとき。シーズン11-1を開始したチームであるニューヨークメッツは、日曜日の午後にフィラデルフィアで行われた最後の11試合の9試合目を失いました。

スティーブンキングのアウトサイダーはトランプ時代のそれです

スティーブンキングのアウトサイダーはトランプ時代のそれです

スティーブン・キングのアウトサイダーは、多くの点で先祖返りの小説であり、80年代の全盛期から引き裂かれたように見える生き物の特徴であり、おそらくセル以来の彼の最もパルプのような本ですが、今日の恐怖の中で間違いなく設立された作品です。表面上は、形を変えるペニーワイズのような子供たちの殺人者を中心としており、その最も暗い脅威は、封じ込められず、神経質に平凡なものよりも幻想的で打ち負かされません。

スティーブンユニバースは、強烈な内部エピソードのペアで、それ自体のバックストーリーをさりげなく粉砕します

スティーブンユニバースは、強烈な内部エピソードのペアで、それ自体のバックストーリーをさりげなく粉砕します

スティーブンユニバースビーチシティのエピソードが実行されるたびに、いくつかのクライマックスイベントが発生し、スティーブンユニバースのより広い神話に対する理解の一部が失われます。これはあなたが期待していたことですか?今日のエピソードは両方とも、容赦なくゆっくりと、シーズンの終盤の主要な部分を設定する決定的な結論に向かって進みます。そして、ロナウドは、静かな納屋が倒れているのを発見した夜中にスティーブンを捕まえるためにやって来ます。月に。

ディズニーワールドの旅行のヒントを教えてください

ディズニーワールドの旅行のヒントを教えてください

「光が触れるものはすべて私たちの王国です。」今週のHackYour Cityでは、1つのテーマパークを取り上げます。

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya shared a sweet photo in honor of boyfriend Tom Holland's 26th birthday Wednesday

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

シーレン「Ms.JuicyBaby」ピアソンは、先月脳卒中で入院した後、「もう一度たくさんのことをする方法を学ばなければならない」ため、言語療法を受けていることを明らかにしました。

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

オスカー受賞者の世紀半ばの家には、3つのベッドルーム、2つのバス、オーシャンフロントの景色があります。

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、生後4か月の娘、モナコに母乳育児をしていると語った。

Come diventare Web Developer?

Come diventare Web Developer?

Vorresti diventare web developer e non sai da dove cominciare?! Qui troverai tutte le risposte necessarie, anche io non sapevo che strada intraprendere ma voglio aiutarti a non commettere i miei stessi errori. Cosa imparare? Le competenza essenziali per qualsiasi web developer sono almeno tre.

投資ノート:Bioscout AU$300万シード

投資ノート:Bioscout AU$300万シード

Bioscoutは、農家を運転席に置くという使命を負っています。Artesian(GrainInnovate)やUniseedと並んで、最新のシードラウンドでチームを支援できることをうれしく思います。問題真菌症による重大な作物の損失は、農民にとって試練であることが証明されています。

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

遠隔医療は、パンデミック後の時代では新しいものではなく、時代遅れの分野でもありません。しかし、業界を詳しく見ると、需要と供給の強力な持続可能性と、米国で絶え間ない革命となる強力な潜在的成長曲線を示しています。

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

2021年は、世界的なベンチャーキャピタル(VC)の資金調達にとって記録的な年でした。DealStreetAsiaによると、東南アジアも例外ではなく、この地域では年間で記録的な25の新しいユニコーンが採掘されました。

Language