[python, C++] Interfacing C++ and Python with the Python API

Interfacing C++ and Python with the Python API

3 Aug 2023CPOL15 min read
This article explains how the Python API makes it possible to embed Python in C++ and write extension modules in C++ that can be imported in Python.
The Python API is a C/C++ programming toolset that enables developers to write code that integrates Python and C++. The first part of the article shows how the Python API makes it possible to access Python code in a C/C++ application. The second part explains how to code extension modules in C++ that can be imported into regular Python code.

1. Introduction

According to StackOverflow, two of the most popular programming languages for desktop development are C++ and Python. Many applications are coded in C++ for performance, and provide a Python interface that enables configuration and scripting. Unfortunately, the two languages are so different that many developers don't know how to access Python code in C++ or call C++ functions from Python.

Thankfully, some implementations of Python (such as the reference implementation at python.org) provide C/C++ headers and libraries that simplify the process of interfacing C++ and Python. These headers and libraries form the Python API, and the goal of this article is to explain how to use Python.

To be specific, this article focuses on two ways of using the Python API. The first part of the article explains how to access Python inside C++ code. This is called embedding Python. The second part explains how to code a C++ library that can be accessed as a Python module. This is called an extension module.

But before I discuss either topic, I need to explain how to download Python and install it on your system. If you're already up to speed on Python, feel free to skip the next section.

2. Installing Python

A Python implementation is a toolset that provides a Python interpreter, basic Python modules, and other utilities such as pip. Based on my experience, there are four main implementations of Python:

  • CPython - oldest and most popular, written in C
  • PyPy - similar to CPython, but uses just-in-time compilation to improve performance
  • Jython - written in Java, converts Python into bytecode
  • IronPython - written in C#, enables Python to access C# and .NET features

CPython is the only Python implementation that provides a C/C++ interface, so this article focuses on CPython. If you're running Linux, you can install it by using your package manager (apt-get install python3.11 python3-dev on Ubuntu, yum install python3 python3-devel on RHEL and CentOS).

If you're running Windows or macOS, you can download an installer from the Python download site. Select your operating system and click the link for the latest version of Python, and your browser will download the executable. When you run the executable, a dialog will ask for configuration settings. The following image shows what this looks like on Windows for version 3.11.4.

At the bottom of the dialog, check the box for Add python.exe to PATH. This ensures that you'll be able to launch the Python interpreter from the command line.

If you click Install Now on Windows, Python will be installed in the AppData\Local\Programs folder. You can customize this by clicking the Customize installation link and selecting a different folder. When the installation is finished, click the dialog's Close button.

For this article, it isn't important where Python is installed, but it is important that you know the installation directory. If you look in the top-level include directory, you'll find the header files for the Python API. The libs directory contains the library required for linking C/C++ applications. On my Windows system, the required library file is named python311.lib. On my Linux system, its name is libpython3.11.so.

3. Embedding Python in C/C++

The Python API provides several header files that declare C/C++ functions capable of accessing Python modules and code. The technical term for accessing Python in external code is called embedding, and the central header file is Python.h.

The goal of this section is to look at the functions in Python.h that can make embedding possible. They can be frustrating to use because Python data structures are all represented by instances of the PyObject data type. Modules are represented by PyObjects, functions and methods are represented by PyObjects, and variables are represented by PyObjects.

This discussion won't discuss all of the functions in the Python API, or even most of them. Instead, we'll look at the functions into two categories:

  1. Fundamental functions - Functions that access modules, methods, and properties
  2. Object creation and conversion - Functions that create PyObjects and convert them to other types

After exploring these functions, this section presents C++ code that reads a function from a simple Python module, sets its parameters, and then executes the Python function.

3.1 Fundamental Functions

To embed Python processing in a C++ application, a developer should be familiar with a central set of functions. Table 1 lists them and provides a description of each.

Table 1: Fundamental Functions of the Python API

Function Signature Description
Py_Initialize() Initializes the interpreter and modules
Py_Finalize() Deallocates the interpreter and resources
PyImport_ImportModule(const char*) Imports the given module
PyObject_HasAttrString(
PyObject*, const char*)
Checks if the attribute is present
PyObject_GetAttrString(
PyObject*, const char*)
Accesses the given attribute
PyCallable_Check(PyObject*) Checks if the attribute can be executed
PyObject_Repr(PyObject*) Creates a PyObject from the printed representation
PyObject_Str(PyObject*) Creates a PyObject from the string representation
PyObject_CallObject(
PyObject*, PyObject*)
Executes the object with arguments
PyINCREF(PyObject*) Increments the reference (can't be null)
PyXINCREF(PyObject*) Increments the reference (can be null)
PyDECREF(PyObject*) Decrements the reference (can't be null)
PyXDECREF(PyObject*) Decrements the reference (can be null)

The first function, Py_Initialize, is particularly important because it performs the tasks needed to make Python available in C/C++. This must be called before the application can access Python modules and features.

After initializing the environment, an application can access Python modules by calling PyImport_ImportModule. This accepts the name of the module and returns a PyObject pointer that represents the module. If the module is contained in a Python file, the *.py suffix should be omitted.

For example, the following function call accesses the code in simple.py:

C++
PyObject *mod = PyImport_ImportModule("simple");

Once an application has accessed a module or data structure, it can examine its attributes. The PyObject_HasAttrString function identifies if an attribute is present. If the attribute is present, PyObject_GetAttrString returns a PyObject pointer representing the attribute.

For example, the following code accesses an attribute named plus from simple.py.

C++
PyObject *mod, *attr;
mod = PyImport_ImportModule("simple");
if (mod != nullptr) {
    if (PyObject_HasAttrString(mod, "plus") == 1) {
        attr = PyObject_GetAttrString(mod, "plus");
    }
}

Properties and functions are both accessed as attributes, but functions can be invoked and properties can't. To check if an attribute can be invoked, an application needs to call PyCallable_Check, which returns 1 if the attribute can be called and 0 if it can't.

If an attribute can be invoked, PyObject_CallObject tells the interpreter to execute the attribute. The first argument is the PyObject pointer representing the attribute and the second is a PyObject pointer that represents a tuple containing the method's arguments.

Every PyObject has a reference count that identifies how many times it's being accessed. When it's created, the count is set to 1. Applications can increment the reference count by calling PyINCREF or PyXINCREF. Both accept a pointer to a PyObject, and the first should only be called if the pointer isn't NULL. The second function, PyXINCREF, can be called if the pointer is null.

When a PyObject is no longer needed, the application should call PyDECREF or PyXDECREF to decrement the object's reference count. Once the count reaches 0, the object will be deallocated. Both functions accept a pointer to a PyObject, and PyDECREF should only be called if the pointer isn't null.

3.2 Object Creation and Conversion

In many cases, an application will need to create a PyObject from regular data or extract regular data from a PyObject. The application may also need to create Python-specific structures like lists or tuples. Table 2 lists the functions that perform these tasks.

Table 2: Object Creation/Conversion Functions

Function Signature Description
PyLong_FromLong(long) Create a PyObject from a long integer
PyLong_AsLong(PyObject*) Return the PyObject's long integer
PyFloat_FromDouble(double) Create a PyObject from a double
PyFloat_AsDouble(PyObject*) Return the PyObject's double
PyUnicode_FromString(const char*) Create a PyObject from a string
PyUnicode_AsEncodedString(
PyObject*, const char*, const char*)
Create a PyObject from the encoded string
PyBytes_FromString(const char*) Create a PyObject from a string
PyBytes_AsString(PyObject*) Return the PyObject's string
PyTuple_New(Py_ssize_t) Create a PyObject representing a tuple
PyTuple_GetItem(PyObject*, Py_ssize_t) Return the given element of a tuple
PyTuple_SetItem(PyObject*, Py_ssize_t,
PyObject*)
Set the given element of a tuple
PyList_New(Py_ssize_t) Create a PyObject representing a list
PyList_GetItem(PyObject*, Py_ssize_t) Return the given element of a list
PyList_SetItem(PyObject*, Py_ssize_t,
PyObject*)
Set the given element of a list

These functions become important when an application needs to read or set an attribute's value. For example, if float_attr is a Python attribute containing a floating-point value, PyFloat_AsDouble will return a double that can be processed in C/C++.

Dealing with text is complicated. The Python API makes it possible to create a unicode PyObject from a string by calling PyUnicode_FromString. You can also create a bytes PyObject from a string by calling PyBytes_FromString.

Displaying an attribute's string is also complicated. PyObject_Str returns a PyObject containing an object's string and PyUnicode_AsEncodedString converts this to a bytes PyObject containing the encoded representation of the string. Then PyBytes_AsString returns the C/C++ string corresponding to the encoded string.

For example, the following code obtains the string representation of the my_attr attribute, encodes it using UTF-8, and prints the corresponding C/C++ string.

C++
PyObject* attr = PyObject_GetAttrString(mod, "my_attr");
PyObject* str = PyObject_Str(attr);
PyObject* ucode = PyUnicode_AsEncodedString(str, "utf-8", NULL);
const char* bytes = PyBytes_AsString(ucode);
std::cout << bytes << std::endl;

To pass arguments to a Python method, an application needs to create a tuple and insert an element for each argument to be passed. In code, the tuple can be created by calling PyTuple_New and elements can be set by calling PyTuple_SetItem. Similarly, an application can create a Python list by calling PyList_New and set its elements by calling PyList_SetItem.

3.3 Simple Embedding Example

To demonstrate how embedding works, the source code for this article contains two source files:

  • simple.py - a simple Python file that defines a function named plus, which returns the sum of its two arguments
  • embedding.cpp - a C++ application that uses the Python API to access the code in simple.py

The following code presents the content of embedding.cpp. This accesses simple.py, finds the plus attribute, sets its arguments, and executes the function.

C++
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <iostream>

int main() {

    PyObject *module, *func, *args, *ret;

    // Initialize python access
    Py_Initialize();

    // Import the simple.py code
    module = PyImport_ImportModule("simple");
    if (module) {

        // Access the attribute named plus
        func = PyObject_GetAttrString(module, "plus");

        // Make sure the attribute is callable
        if (func && PyCallable_Check(func)) {

            // Create a tuple to contain the function's args
            args = PyTuple_New(2);
            PyTuple_SetItem(args, 0, PyLong_FromLong(4));
            PyTuple_SetItem(args, 1, PyLong_FromLong(7));

            // Execute the plus function in simple.py
            ret = PyObject_CallObject(func, args);
            Py_DECREF(args);
            Py_DECREF(func);
            Py_DECREF(module);

            // Check the return value
            if (ret) {

                // Convert the value to long and print
                long retVal = PyLong_AsLong(ret);
                std::cout << "Result: " << retVal << std::endl;
            }
            else {

                // Display error
                PyErr_Print();
                std::cerr << "Couldn't access return value" << std::endl;
                Py_Finalize();
                return 1;
            }
        }
        else {

            // Display error
            if (PyErr_Occurred())
                PyErr_Print();
            std::cerr << "Couldn't execute function" << std::endl;
        }
    }
    else {

        // Display error
        PyErr_Print();
        std::cerr << "Couldn't access module" << std::endl;
        Py_Finalize();
        return 1;
    }

    // Finalize the Python embedding
    Py_Finalize();
    return 0;
}

After accessing the module, the application invokes the module's plus function by calling PyObject_CallObject. It passes two arguments: the attribute representing the function and a tuple containing the two values to be passed to the plus function. The following code shows what the plus function in simple.py looks like.

Python
def plus(a, b):
    return a + b

To build an application from embedding.cpp, you'll need to tell the compiler about the header files in the include folder of the Python installation directory and the library file in the libs folder. When I run the application on my system, the output is given as follows:

 
Result: 11

4. Creating a Python Extension

A Python interpreter can access built-in modules that include osdatetime, and string. Using the Python API, we can add new built-in modules called extension modules. Unlike regular modules, extension modules are dynamic libraries coded in C or C++.

This discussion walks through the development of an extension module named plustwo. This contains a function named addtwo, which accepts a number and returns the sum of the number and 2.

Python
python
>>> import plustwo
>>> x = plustwo.addtwo(5)
>>> x
7

Programming extension modules is hard because the functions need to have special names and they have to provide special data structures. To understand the process, you need to be aware of three points:

  1. If the desired module is modname, the code must define a function named PyInit_modname that doesn't accept any parameters. For the example, the module is named plustwo, so the code defines a function named PyInit_plustwo.
  2. To describe the module, the code must create a PyModuleDef structure and set its fields. These fields identify the module's name, its documentation, and its methods.
  3. For each function in the module, the code must create a PyMethodDef structure and set its fields. These fields identify the method's name, arguments, and documentation. It must also identify the function that will be called when the method is invoked.

This section discusses these points in detail and then shows how the plustwo extension module can be implemented in code.

4.1 The PyInit Function

When a Python interpreter imports the extension module modname for the first time, it will call the PyInit_modname function. This must be coded properly to ensure that the interpreter can execute it, and there are five rules to follow:

  • It must be preceded by the PyMODINIT_FUNC macro, and it must be the only function preceded by this macro.
  • It must not be static, and it must be the only non-static item in the code.
  • It can't accept any parameters.
  • It must call PyModuleCreate with a reference to the PyModuleDef that describes the module.
  • Its return value must be set to the return value of PyModuleCreate.

The best way to understand these rules is to look at an example. If the module name is plustwo and the PyModuleDef structure that describes the module is moduleDef, the following code shows how PyInit_plustwo can be coded:

C++
PyMODINIT_FUNC PyInit_plustwo() {
    return PyModule_Create(&moduleDef);
}

At minimum, the function needs to call PyModule_Create with a PyModuleDef reference and return the result. But the function can be coded to do more than call PyModule_Create.

4.2 The PyModuleDef Structure

The extension module needs to create a PyModuleDef structure to tell the Python interpreter how the module should be processed. Table 3 lists each of the fields of this structure and their data types.

Table 3: Fields of the PyModuleDef Structure

Field Name Data Type Description
m_base PyModuleDef_Base Always set to PyModuleDef_HEAD_INIT
m_name const char* The module's name
m_doc const char* The module's description
m_size Py_ssize_t Size of memory to store module state
m_methods PyMethodDef* Array of method descriptors
m_slots PyMethodDef_Slot* Array of method slots
m_traverse traverseproc Traversal function
m_clear inquiry Inquiry function
m_free freefunc Function that frees resources

This article focuses on the first five fields, and the first should always be set to PyModuleDef_HEAD_INIT. The second should be set to the module's name and the third should be set to the module's docstring, which is displayed when the help function is called.

The fourth field is important for modules that require multi-phase initialization and sub-interpreters. This field identifies how much memory should be set aside to store the module's state data. This isn't a concern for most extension modules, so m_size should be set to -1. This is shown in the following code:

C++
static struct PyModuleDef moduleDef = {
    PyModuleDef_HEAD_INIT, 
    "plustwo", 
    "This module contains a function (addtwo) that adds two to a number\n", 
    -1, 
    funcs  // Array containing a PyMethodDef for each module function
};

The m_methods field must be set to an array containing a PyMethodDef structure for each function contained in the module. In the example, the plustwo module has one function named addtwo. Therefore, the funcs array in the example code contains one PyMethodDef structure.

4.3 The PyMethodDef Structure

An extension module identifies its functions by providing an array of PyMethodDef structures. The fields of a PyMethodDef identify the function's name, arguments, and docstring. Table 4 lists these fields and their data types.

Table 4: Fields of the PyMethodDef Structure

Field Name Data Type Description
ml_name const char* The function's name
ml_meth PyCFunction The C function that provides the code
ml_flags int Flags that identify the function's arguments
ml_doc const char* The function's docstring

The second field, ml_meth, must be set to a C function that provides the code to be executed when the module's function is called. When coding this function, there are four rules to keep in mind:

  1. If the module function has a different name than the module, the name of the C function should be set to modname_funcname, where modname is the name of the module and funcname is the name of the function.
  2. If the module function has the same name as its surrounding module, the name of the C function should be set to modname.
  3. The number of arguments accepted by the function is determined by the ml_flags argument of the PyMethodDef.
  4. The C function must be declared static and it must return a PyObject pointer. If the function doesn't return a value, it should use Py_RETURN_NONE to return an empty object.

The third field, ml_flags, identifies the nature of the arguments accepted by the function. This is usually set to one of three values:

  • METH_NOARGS - The function accepts a single PyObject* argument that represents the module.
  • METH_O - The function accepts two arguments: a PyObject* representing the module and a PyObject* that represents the single argument.
  • METH_VARARGS - The function accepts two arguments: a PyObject* representing the module and a PyObject* that represents a tuple containing the function's parameters.

For this article's example, the addtwo function accepts a numeric argument and returns the sum of the argument and 2. Because there's only one argument, ml_flags should be set to METH_O.

4.4 The plustwo Extension Module

At this point, you should have a basic grasp of the functions and data structures that must be created in an extension module. The following listing presents the code in plustwo.cpp, which is part of this article's source code. This file defines an extension module named plustwo containing a function named addtwo:

C++
#define PY_SSIZE_T_CLEAN
#include <Python.h>

// The code to be executed when the module function is called
static PyObject* plustwo_addtwo(PyObject* self, PyObject* arg) {
    long longArg = PyLong_AsLong(arg) + 2;
    return PyLong_FromLong(longArg);
}

// Array of PyMethodDef structures - describe the module's functions
static PyMethodDef funcs[] = {
    {"addtwo", (PyCFunction)plustwo_addtwo, METH_O, "This adds two to a number\n"},
    {NULL, NULL, 0, NULL}
};

// The PyModuleDef structure describes the module
static struct PyModuleDef moduleDef = {
    PyModuleDef_HEAD_INIT, 
    "plustwo", 
    "This module contains a function (addtwo) that adds two to a number\n", 
    -1, 
    funcs
};

// Called when the interpreter imports the module
PyMODINIT_FUNC PyInit_plustwo() {
    return PyModule_Create(&moduleDef);
}

As you look at this code, there are a few items to notice:

  • All the functions and structures are static except for PyInit_plustwo at the end.
  • The function corresponding to the addtwo module function is called plustwo_addtwo because the module function has a different name than the module.
  • The module only has one function, but the array of PyMethodDefs has two elements. The second element defines a null function, and if this isn't present, the code won't work.
  • The third argument of the PyMethodDef is METH_O, which specifies that the function only accepts one argument. But in code, plustwo_addtwo accepts two arguments: a PyObject representing the module and a PyObject representing the input argument.

To serve as an extension module, this code must be compiled as a dynamic library (plustwo.dll on Windows, plustwo.so on Linux and macOS). On Windows, plustwo.dll must be renamed to plustwo.pyd, which identifies the file as a Python dynamic module. On Linux, the *.so suffix can be left unchanged.

Once the extension module is created, you can test it by opening a Python prompt. Then you can import the plustwo module and call the addtwo function with a session like the following:

Python
python
>>> import plustwo
>>> x = plustwo.addtwo(5)
>>> x
7

5. History

  • 2nd August, 2023: Initial submission
  • 4th August, 2023: Fixed code labels
  • 9th August, 2023: Added calls to PyFinalize

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

 

Written By
 
United States United States
I've been a programmer, engineer, and author for over 20 years.

 

[출처] https://www.codeproject.com/Articles/5365450/Interfacing-Cplusplus-and-Python-with-the-Python-A

 

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

source_code.zip

 

C++ 및 Python과 Python API의 인터페이스

2023년 8월 3일CPOL15분 읽기
이 문서에서는 Python API를 사용하여 Python을 C++에 포함하고 Python에서 가져올 수 있는 C++의 확장 모듈을 작성할 수 있는 방법을 설명합니다.
Python API는 개발자가 Python과 C++를 통합하는 코드를 작성할 수 있도록 하는 C/C++ 프로그래밍 도구 집합입니다. 기사의 첫 번째 부분에서는 Python API를 사용하여 C/C++ 애플리케이션에서 Python 코드에 액세스할 수 있는 방법을 보여줍니다. 두 번째 부분에서는 일반 Python 코드로 가져올 수 있는 확장 모듈을 C++로 코딩하는 방법을 설명합니다.

1. 소개

StackOverflow 에 따르면 데스크톱 개발에 가장 많이 사용되는 두 가지 프로그래밍 언어는 C++ 및 Python입니다. 많은 애플리케이션은 성능을 위해 C++로 코딩되며 구성 및 스크립팅을 가능하게 하는 Python 인터페이스를 제공합니다. 안타깝게도 두 언어는 너무 다르기 때문에 많은 개발자가 C++에서 Python 코드에 액세스하는 방법이나 Python에서 C++ 함수를 호출하는 방법을 모릅니다.

고맙게도 Python의 일부 구현(예: python.org의 참조 구현)은 C++와 Python의 인터페이스 프로세스를 단순화하는 C/C++ 헤더 및 라이브러리를 제공합니다. 이러한 헤더와 라이브러리는 Python API를 구성하며 이 기사의 목표는 Python을 사용하는 방법을 설명하는 것입니다.

구체적으로 이 기사는 Python API를 사용하는 두 가지 방법에 중점을 둡니다. 기사의 첫 번째 부분에서는 C++ 코드 내에서 Python에 액세스하는 방법을 설명합니다. 이것을 임베딩 파이썬이라고 합니다. 두 번째 부분에서는 Python 모듈로 액세스할 수 있는 C++ 라이브러리를 코딩하는 방법을 설명합니다. 이것을 확장 모듈 이라고 합니다 .

그러나 두 주제에 대해 논의하기 전에 Python을 다운로드하고 시스템에 설치하는 방법을 설명해야 합니다. Python에 대해 이미 알고 있다면 다음 섹션을 건너뛰어도 됩니다.

2. 파이썬 설치하기

Python 구현은 Python 인터프리터, 기본 Python 모듈 및 pip와 같은 기타 유틸리티를 제공하는 도구 세트입니다. 내 경험에 따르면 Python에는 네 가지 주요 구현이 있습니다.

  • CPython - C로 작성된 가장 오래되고 인기 있는
  • PyPy - CPython과 유사하지만 JIT(Just-In-Time) 컴파일을 사용하여 성능을 향상시킵니다.
  • Jython - Java로 작성, Python을 바이트코드로 변환
  • IronPython - C#으로 작성되어 Python에서 C# 및 .NET 기능에 액세스할 수 있습니다.

CPython은 C/C++ 인터페이스를 제공하는 유일한 Python 구현이므로 이 기사에서는 CPython에 중점을 둡니다. Linux를 실행 중인 경우 패키지 관리자( apt-get install python3.11 python3-devUbuntu, yum install python3 python3-develRHEL 및 CentOS)를 사용하여 설치할 수 있습니다.

Windows 또는 macOS를 실행 중인 경우 Python 다운로드 사이트 에서 설치 프로그램을 다운로드할 수 있습니다 . 운영 체제를 선택하고 최신 버전의 Python 링크를 클릭하면 브라우저가 실행 파일을 다운로드합니다. 실행 파일을 실행하면 구성 설정을 묻는 대화 상자가 나타납니다. 다음 이미지는 이것이 Windows 버전 3.11.4에서 어떻게 보이는지 보여줍니다.

대화 상자 하단에서 Add python.exe to PATH 상자를 선택합니다 . 이렇게 하면 명령줄에서 Python 인터프리터를 시작할 수 있습니다.

Windows에서 지금 설치를 클릭하면 Python이 AppData\Local\Programs 폴더 에 설치됩니다 설치 사용자 지정 링크를 클릭하고 다른 폴더를 선택하여 이를 사용자 지정할 수 있습니다 . 설치가 완료되면 대화 상자의 닫기 버튼을 클릭합니다.

이 기사에서는 Python이 설치된 위치가 중요하지 않지만 설치 디렉토리를 아는 것이 중요합니다. 최상위 수준 포함 디렉터리를 보면 Python API의 헤더 파일을 찾을 수 있습니다. libs 디렉토리에는 C/C++ 응용 프로그램을 연결하는  필요한 라이브러리가 포함되어 있습니다. 내 Windows 시스템에서 필요한 라이브러리 파일의 이름은 python311.lib 입니다 . 내 Linux 시스템에서 그 이름은 libpython3.11.so 입니다 .

3. C/C++에 파이썬 내장하기

Python API는 Python 모듈 및 코드에 액세스할 수 있는 C/C++ 함수를 선언하는 여러 헤더 파일을 제공합니다. 외부 코드에서 Python에 액세스하기 위한 기술 용어를 embedding 이라고 하며 중앙 헤더 파일은 Python.h 입니다 .

이 섹션의 목표 는 내장을 가능하게 할 수 있는 Python.h 의 함수를 살펴보는 것입니다 . Python 데이터 구조는 모두 데이터 유형의 인스턴스로 표현되기 때문에 사용하기 어려울 수 있습니다 PyObject모듈은 s로 표시되고 PyObject함수 및 메소드는 s로 표시되며 변수는 PyObject로 표시됩니다 .PyObject

이 토론에서는 Python API의 모든 기능 또는 대부분의 기능에 대해 설명하지 않습니다. 대신 함수를 두 가지 범주로 살펴보겠습니다.

  1. 기본 기능 - 모듈, 메서드 및 속성에 액세스하는 기능
  2. 객체 생성 및 변환 - s를 생성 PyObject하고 다른 유형으로 변환하는 기능

이러한 함수를 탐색한 후 이 섹션에서는 간단한 Python 모듈에서 함수를 읽고 해당 매개 변수를 설정한 다음 Python 함수를 실행하는 C++ 코드를 제시합니다.

3.1 기본 기능

C++ 애플리케이션에 Python 처리를 포함하려면 개발자가 중앙 함수 세트에 익숙해야 합니다. 표 1은 이들을 나열하고 각각에 대한 설명을 제공합니다.

표 1: Python API의 기본 기능

함수 서명 설명
Py_Initialize() 인터프리터 및 모듈 초기화
Py_Finalize() 인터프리터와 리소스 할당 해제
PyImport_ImportModule(const char*) 주어진 모듈을 가져옵니다
PyObject_HasAttrString(
PyObject*, const char*)
속성이 존재하는지 확인
PyObject_GetAttrString(
PyObject*, const char*)
주어진 속성에 접근
PyCallable_Check(PyObject*) 속성을 실행할 수 있는지 확인합니다.
PyObject_Repr(PyObject*) PyObject인쇄된 표현에서 생성
PyObject_Str(PyObject*) PyObject문자열 표현에서 생성
PyObject_CallObject(
PyObject*, PyObject*)
인수를 사용하여 개체를 실행합니다.
PyINCREF(PyObject*) 참조 증가( 될 수 없음 null)
PyXINCREF(PyObject*) 참조 증가( 일 수 있음 null)
PyDECREF(PyObject*) 참조 감소( 될 수 없음 null)
PyXDECREF(PyObject*) 참조 감소( 일 수 있음 null)

첫 번째 함수인 는 Py_InitializePython을 C/C++에서 사용할 수 있도록 하는 데 필요한 작업을 수행하기 때문에 특히 중요합니다. 애플리케이션이 Python 모듈 및 기능에 액세스하기 전에 호출해야 합니다.

환경을 초기화한 후 애플리케이션은 를 호출하여 Python 모듈에 액세스할 수 있습니다 PyImport_ImportModule이것은 모듈의 이름을 받아들이고 PyObject모듈을 나타내는 포인터를 반환합니다. 모듈이 Python 파일에 포함된 경우 *.py 접미사는 생략해야 합니다.

예를 들어 다음 함수 호출은 simple.py 의 코드에 액세스합니다 .

C++
PyObject *mod = PyImport_ImportModule( " 단순" );

애플리케이션이 모듈이나 데이터 구조에 액세스하면 해당 속성을 검사할 수 있습니다. 이 PyObject_HasAttrString함수는 속성이 있는지 식별합니다. 속성이 있으면 속성을 나타내는 포인터를 PyObject_GetAttrString반환합니다 .PyObject

예를 들어 다음 코드는 simple.pyplus 에서 명명된 특성에 액세스합니다 .

C++
파이오브젝트 *mod, *attr;
mod = PyImport_ImportModule( " 단순" );
if (mod != nullptr ) {
     if (PyObject_HasAttrString(mod, " plus" ) == 1 ) {
        attr = PyObject_GetAttrString(mod, " 더하기" );
    }
}

속성과 함수는 모두 특성으로 액세스되지만 함수는 호출할 수 있지만 속성은 호출할 수 없습니다. 속성을 호출할 수 있는지 확인하려면 애플리케이션에서 속성을 호출할 수 있는지 여부를 반환 PyCallable_Check하는 를 호출해야 합니다.10

속성을 호출할 수 있는 경우 PyObject_CallObject인터프리터에게 속성을 실행하도록 지시합니다. 첫 번째 인수는 PyObject특성을 나타내는 포인터이고 두 번째 인수는 PyObject메서드의 인수를 포함하는 튜플을 나타내는 포인터입니다.

모든 항목 PyObject에는 액세스되는 횟수를 식별하는 참조 횟수가 있습니다. 생성될 때 개수는 로 설정됩니다 1PyINCREF애플리케이션은 또는 를 호출하여 참조 횟수를 증가시킬 수 있습니다 PyXINCREF둘 다 a 에 대한 포인터를 허용 PyObject하고 첫 번째 포인터는 포인터가 아닌 경우에만 호출해야 합니다 NULL두 번째 함수 는 PyXINCREF포인터가 이면 호출할 수 있습니다 null.

a가 PyObject더 이상 필요하지 않으면 응용 프로그램은 개체의 참조 횟수를 줄이기 위해 PyDECREF또는을 호출해야 합니다. PyXDECREF개수에 도달하면 0개체가 할당 해제됩니다. 두 함수 모두 a 에 대한 포인터를 허용하며 PyObject포인터 PyDECREF가 null이 아닌 경우에만 호출해야 합니다.

3.2 객체 생성 및 변환

PyObject대부분의 경우 애플리케이션은 일반 데이터에서 를 생성하거나 PyObject응용 프로그램은 목록이나 튜플과 같은 Python 관련 구조를 만들어야 할 수도 있습니다. 표 2에는 이러한 작업을 수행하는 기능이 나열되어 있습니다.

표 2: 개체 생성/변환 기능

함수 서명 설명
PyLong_FromLong(long) PyObject긴 정수에서 만들기
PyLong_AsLong(PyObject*) PyObject의 긴 정수를 반환합니다.
PyFloat_FromDouble(double) PyObjectdouble에서 만들기
PyFloat_AsDouble(PyObject*) PyObject의 double을 반환합니다.
PyUnicode_FromString(const char*) PyObject문자열에서 만들기
PyUnicode_AsEncodedString(
PyObject*, const char*, const char*)
PyObject인코딩된 문자열에서 만들기
PyBytes_FromString(const char*) PyObject문자열에서 만들기
PyBytes_AsString(PyObject*) PyObject의 문자열을 반환
PyTuple_New(Py_ssize_t) PyObject튜플을 나타내는 만들기
PyTuple_GetItem(PyObject*, Py_ssize_t) 튜플의 주어진 요소를 반환
PyTuple_SetItem(PyObject*, Py_ssize_t,
PyObject*)
튜플의 주어진 요소 설정
PyList_New(Py_ssize_t) PyObject목록을 나타내는 만들기
PyList_GetItem(PyObject*, Py_ssize_t) 목록의 주어진 요소를 반환
PyList_SetItem(PyObject*, Py_ssize_t,
PyObject*)
목록의 주어진 요소 설정

이러한 기능은 애플리케이션이 속성 값을 읽거나 설정해야 할 때 중요해집니다. 예를 들어 가 float_attr부동 소수점 값을 포함하는 Python 특성인 경우 C/C++에서 처리할 수 있는 PyFloat_AsDouble를 반환합니다 .double

텍스트를 다루는 것은 복잡합니다. Python API를 사용하면 를 호출하여 PyObject에서 유니코드를 생성할 수 있습니다 를 호출하여 a에서 바이트를 만들 수도 있습니다 .stringPyUnicode_FromStringPyObjectstringPyBytes_FromString

속성을 표시하는 string것도 복잡합니다. 객체를 포함하는 PyObject_Str를 반환 하고 이를 의 인코딩된 표현을 포함하는 바이트로 변환합니다 그런 다음 인코딩된 에 해당하는 C/C++를 반환합니다 .PyObjectstringPyUnicode_AsEncodedStringPyObjectstringPyBytes_AsStringstringstring

예를 들어 다음 코드는 속성 string의 표현을 가져와 my_attrUTF-8을 사용하여 인코딩하고 해당 C/C++ 를 인쇄합니다 string.

C++
PyObject* attr = PyObject_GetAttrString(mod, " my_attr" );
PyObject* str = PyObject_Str(attr);
PyObject* ucode = PyUnicode_AsEncodedString(str, " utf-8" , NULL);
const  char * 바이트 = PyBytes_AsString(ucode);
std::cout  < < 바이트 < <  std::endl ;

Python 메서드에 인수를 전달하려면 응용 프로그램에서 튜플을 만들고 전달할 각 인수에 대한 요소를 삽입해야 합니다. 코드에서 튜플은 를 호출하여 생성할 수 PyTuple_New있고 요소는 를 호출하여 설정할 수 있습니다 PyTuple_SetItem마찬가지로 애플리케이션은 를 호출하여 Python 목록을 만들고 를 호출 PyList_New하여 해당 요소를 설정할 수 있습니다 PyList_SetItem.

3.3 간단한 임베딩 예제

임베딩 작동 방식을 보여주기 위해 이 문서의 소스 코드에는 두 개의 소스 파일이 포함되어 있습니다.

  • simple.pyplus - 두 인수의 합을 반환하는 이라는함수를 정의하는 간단한 Python 파일
  • embedding.cpp - Python API를 사용하여 simple.py 의 코드에 액세스하는 C++ 애플리케이션

다음 코드는 embedding.cpp 의 내용을 나타냅니다 . 이것은 simple.py 에 액세스하고 , 속성을 찾고 plus, 인수를 설정하고, 함수를 실행합니다.

C++
#define PY_SSIZE_T_CLEAN
 #include < Python.h > #include < iostream > int main() { 
 



    PyObject *모듈, *func, *args, *ret;

    // 파이썬 액세스 초기화
     Py_Initialize();

    // simple.py 코드 가져오기
     module = PyImport_ImportModule( " simple" );
    if (모듈) {

        // plus func라는 속성에 액세스
         = PyObject_GetAttrString(module, " plus" );

        // 속성이 호출 가능한지 확인
         if (func && PyCallable_Check(func)) {

            // 함수의 인수를 포함할 튜플을 만듭니다.
             args = PyTuple_New( 2 );
            PyTuple_SetItem(args, 0 , PyLong_FromLong( 4 ));
            PyTuple_SetItem(args, 1 , PyLong_FromLong( 7 ));

            // simple.py에서 더하기 함수를 실행합니다.
             ret = PyObject_CallObject(func, args);
            Py_DECREF(인자);
            Py_DECREF(펑크);
            Py_DECREF(모듈);

            // 반환값 확인
             if (ret) {

                // 값을 long으로 변환하고
                 long을 출력합니다 . retVal = PyLong_AsLong(ret);
                std::cout  < <  " 결과: "  < < retVal < <  std::endl ;
            }
            다른 {

                // 오류 표시
                 PyErr_Print();
                std::cerr  < <  " 반환 값에 액세스할 수 없습니다."  < <  std::endl ;
                Py_Finalize();
                반환  1 ;
            }
        }
        다른 {

                        // (PyErr_Occurred()) 인 경우 오류 표시

                PyErr_Print();
            std::cerr  < <  " 함수를 실행할 수 없습니다."  < <  std::endl ;
        }
    }
    다른 {

        // 오류 표시
         PyErr_Print();
        std::cerr  < <  " 모듈에 액세스할 수 없습니다."  < <  std::endl ;
        Py_Finalize();
        반환  1 ;
    }

    // Python 임베딩을 마무리합니다.
     Py_Finalize();
    반환  0 ;
}

모듈에 액세스한 후 애플리케이션은 를 plus호출하여 모듈의 기능을 호출합니다 PyObject_CallObject함수를 나타내는 속성과 함수에 전달할 두 값을 포함하는 튜플의 두 인수를 전달합니다 plus다음 코드는 simple.pyplus 의 함수가 어떻게 생겼는지 보여줍니다.

파이썬
def plus(a, b):
     a + b 반환

embedding.cpp 에서 애플리케이션을 빌드하려면 Python 설치 디렉터리의 include 폴더에 있는 헤더 파일과 libs 폴더 에 있는 라이브러리 파일에 대해 컴파일러에 알려야 합니다 내 시스템에서 응용 프로그램을 실행하면 출력이 다음과 같이 제공됩니다.

 
결과: 11

4. 파이썬 확장 생성

Python 인터프리터는 및 를 포함하는 내장 모듈에 액세스할 수 있습니다 . Python API를 사용하여 확장 모듈 이라는 새로운 내장 모듈을 추가할 수 있습니다 일반 모듈과 달리 확장 모듈은 C 또는 C++로 코딩된 동적 라이브러리입니다.osdatetimestring

이 토론에서는 이라는 확장 모듈의 개발 과정을 안내합니다 plustwoaddtwo여기에는 숫자를 받아들이고 숫자와 2의 합을 반환하는 이라는 함수가 포함되어 있습니다 .

파이썬
파이썬
>>> 플러스투 가져오기
>>> x = plustwo.addtwo( 5 )
>>> 엑스
7

확장 모듈 프로그래밍은 함수가 특별한 이름을 가져야 하고 특별한 데이터 구조를 제공해야 하기 때문에 어렵습니다. 프로세스를 이해하려면 다음 세 가지 사항을 알아야 합니다.

  1. 원하는 모듈이 인 경우 modname코드는 PyInit_modname매개변수를 허용하지 않는 명명된 함수를 정의해야 합니다. 예를 들어, 모듈 이름이 plustwo이므로 코드는 이라는 함수를 정의합니다 PyInit_plustwo.
  2. 모듈을 설명하려면 코드에서 PyModuleDef구조를 만들고 해당 필드를 설정해야 합니다. 이 필드는 모듈의 이름, 설명서 및 메서드를 식별합니다.
  3. 모듈의 각 함수에 대해 코드는 PyMethodDef구조를 만들고 해당 필드를 설정해야 합니다. 이 필드는 메소드의 이름, 인수 및 문서를 식별합니다. 또한 메소드가 호출될 때 호출될 함수를 식별해야 합니다.

이 섹션에서는 이러한 사항에 대해 자세히 설명하고 plustwo코드에서 확장 모듈을 구현하는 방법을 보여줍니다.

4.1 PyInit 함수

Python 인터프리터가 modname처음으로 확장 모듈을 가져올 때 함수를 호출합니다. 이것은 인터프리터가 실행할 수 있도록 적절하게 코딩되어야 하며 따라야 할 다섯 가지 규칙이 있습니다.PyInit_modname

  • 매크로 앞에 와야 하며 PyMODINIT_FUNC이 매크로 앞에 오는 유일한 함수여야 합니다.
  • 아니어야 하며 코드에서 static유일한 비항목이어야 합니다 .static
  • 어떤 매개변수도 받아들일 수 없습니다.
  • 모듈을 설명하는 에 PyModuleCreate대한 참조로 호출해야 합니다 .PyModuleDef
  • 반환 값은 의 반환 값으로 설정되어야 합니다 PyModuleCreate.

이러한 규칙을 이해하는 가장 좋은 방법은 예제를 보는 것입니다. 모듈 이름이 이고 모듈을 설명하는 구조가 인 plustwo경우 다음 코드는 코딩 방법을 보여줍니다.PyModuleDefmoduleDefPyInit_plustwo

C++
PyMODINIT_FUNC PyInit_plustwo() {
     return PyModule_Create(&moduleDef);
}

최소한 함수는 참조 PyModule_Create를 사용 하여 호출 PyModuleDef하고 결과를 반환해야 합니다. 그러나 함수는 call 이상을 수행하도록 코딩할 수 있습니다 PyModule_Create.

4.2 PyModuleDef 구조

PyModuleDef확장 모듈은 파이썬 인터프리터에게 모듈 처리 방법을 알려주는 구조를 만들어야 합니다 . 표 3에는 이 구조의 각 필드와 해당 데이터 유형이 나열되어 있습니다.

표 3: PyModuleDef 구조의 필드

분야 명 데이터 형식 설명
m_base PyModuleDef_Base 항상 다음으로 설정PyModuleDef_HEAD_INIT
m_name const char* 모듈의 이름
m_doc const char* 모듈 설명
m_size Py_ssize_t 모듈 상태를 저장할 메모리 크기
m_methods PyMethodDef* 메서드 설명자 배열
m_slots PyMethodDef_Slot* 메서드 슬롯 배열
m_traverse traverseproc 순회 기능
m_clear inquiry 문의 기능
m_free freefunc 리소스를 해제하는 기능

이 문서는 처음 5개 필드에 중점을 두며 첫 번째 필드는 항상 로 설정해야 합니다 PyModuleDef_HEAD_INIT두 번째는 모듈의 이름으로 설정되어야 하고 세 번째는 함수가 호출될 docstring때 표시되는 모듈의 로 설정되어야 합니다 .help

네 번째 필드는 다단계 초기화 및 하위 해석기가 필요한 모듈에 중요합니다. 이 필드는 모듈의 상태 데이터를 저장하기 위해 따로 설정해야 하는 메모리 양을 식별합니다. 이것은 대부분의 확장 모듈에서 문제가 되지 않으므로 m_size로 설정해야 합니다 -1이는 다음 코드에 나와 있습니다.

C++
정적  구조체 PyModuleDef moduleDef = {
    PyModuleDef_HEAD_INIT,
    " plustwo" , 
     " 이 모듈에는 숫자에 2를 더하는 함수(addtwo)가 포함되어 있습니다\n" ,
    - 1 ,
    funcs   // 각 모듈에 대한 PyMethodDef를 포함하는 배열 function
 };

필드 는 모듈에 포함된 각 함수의 구조를 m_methods포함하는 배열로 설정되어야 합니다 . PyMethodDef이 예에서 plustwo모듈에는 이라는 하나의 함수가 있습니다 addtwo따라서 funcs예제 코드의 배열에는 하나의 PyMethodDef구조가 포함됩니다.

4.3 PyMethodDef 구조

확장 모듈은 구조 배열을 제공하여 기능을 식별합니다 PyMethodDef의 필드는 PyMethodDef함수의 이름, 인수 및 독스트링을 식별합니다. 표 4에는 이러한 필드와 해당 데이터 유형이 나열되어 있습니다.

표 4: PyMethodDef 구조의 필드

분야 명 데이터 형식 설명
ml_name const char* 함수의 이름
ml_meth PyCFunction 코드를 제공하는 C 함수
ml_flags int 함수의 인수를 식별하는 플래그
ml_doc const char* 함수의docstring

두 번째 필드인 는 ml_meth모듈의 함수가 호출될 때 실행될 코드를 제공하는 C 함수로 설정되어야 합니다. 이 함수를 코딩할 때 염두에 두어야 할 네 가지 규칙이 있습니다.

  1. 모듈 함수 이름이 모듈 이름과 다른 경우 C 함수 이름을 로 설정해야 합니다 . 여기서 는 모듈 이름이고 는 함수 이름입니다.modname_funcnamemodnamefuncname
  2. 모듈 함수가 주변 모듈과 이름이 같으면 C 함수 이름을 로 설정해야 합니다 modname.
  3. 함수에서 허용하는 인수의 수는 ml_flags의 인수 에 의해 결정됩니다 PyMethodDef.
  4. C 함수는 선언되어야 하며 포인터 static를 반환해야 합니다 PyObject함수가 값을 반환하지 않으면 Py_RETURN_NONE빈 개체를 반환하는 데 사용해야 합니다.

세 번째 필드인 는 ml_flags함수에서 허용하는 인수의 특성을 식별합니다. 일반적으로 다음 세 값 중 하나로 설정됩니다.

  • METH_NOARGS- 함수는 PyObject*모듈을 나타내는 단일 인수를 허용합니다.
  • METH_OPyObject*- 이 함수는 모듈을 나타내는 a와 PyObject*단일 인수를 나타내는 a의 두 가지 인수를 허용합니다 .
  • METH_VARARGSPyObject*- 이 함수는 모듈을 나타내는 a와 PyObject*함수의 매개변수를 포함하는 튜플을 나타내는 a의 두 가지 인수를 허용합니다 .

이 문서의 예에서 addtwo함수는 숫자 인수를 허용하고 인수와 2의 합계를 반환합니다. 인수가 하나뿐이므로 를 ml_flags로 설정해야 합니다 METH_O.

4.4 plustwo 확장 모듈

이 시점에서 확장 모듈에서 만들어야 하는 기능 및 데이터 구조에 대한 기본적인 이해가 있어야 합니다. 다음 목록은 이 문서의 소스 코드의 일부인 plustwo.cpp 의 코드를 보여줍니다. plustwo이 파일은 다음과 같은 함수를 포함하는 확장 모듈을 정의합니다 addtwo.

C++
#define PY_SSIZE_T_CLEAN
 #include < Python.h > // 모듈 함수가 호출될 때 실행할 코드
 static PyObject* plustwo_addtwo(PyObject* self, PyObject* arg) {
     long longArg = PyLong_AsLong(arg) + 2 ;
    return PyLong_FromLong(longArg); 


}

// PyMethodDef 구조의 배열 - 모듈의 함수를 설명합니다.
 static PyMethodDef funcs[] = {
    { " addtwo" , (PyCFunction)plustwo_addtwo, METH_O, " 이것은 숫자에 2를 더합니다\n" },
    {NULL, NULL, 0 , NULL}
};

// PyModuleDef 구조체는 모듈
 정적  구조체를 설명합니다. PyModuleDef moduleDef = {
    PyModuleDef_HEAD_INIT,
    " plustwo" , 
     " 이 모듈에는 숫자에 2를 더하는 함수(addtwo)가 포함되어 있습니다\n" ,
    - 1 ,
    기능
};

// 인터프리터가 모듈을 가져올 때 호출됨
 PyMODINIT_FUNC PyInit_plustwo() {
     return PyModule_Create(&moduleDef);
}

이 코드를 살펴보면 몇 가지 주목할 사항이 있습니다.

  • 모든 기능과 구조는 마지막을 static제외하고 있습니다.PyInit_plustwo
  • 모듈 함수 는 모듈과 이름이 다르기 때문에 모듈 함수 에 해당하는 함수가 addtwo호출됩니다 .plustwo_addtwo
  • 모듈에는 하나의 기능만 있지만 PyMethodDefs의 배열에는 두 개의 요소가 있습니다. 두 번째 요소는 null함수를 정의하며 이것이 없으면 코드가 작동하지 않습니다.
  • PyMethodDefis 의 세 번째 인수 METH_O는 함수가 하나의 인수만 허용하도록 지정합니다. 그러나 코드에서는 모듈을 나타내는 a와 입력 인수를 나타내는 plustwo_addtwo두 가지 인수를 허용합니다 .PyObjectPyObject

확장 모듈로 사용하려면 이 코드를 동적 라이브러리( Windows의 경우 plustwo.dll , Linux 및 macOS의 경우 plustwo.so )로 컴파일해야 합니다. Windows에서 plustwo.dll은 파일을 Python 동적 모듈로 식별하는 plustwo.pyd 로 이름을 바꿔야 합니다 . Linux에서는 *.so 접미사를 변경하지 않고 그대로 둘 수 있습니다.

확장 모듈이 생성되면 Python 프롬프트를 열어 테스트할 수 있습니다. 그런 다음 모듈을 가져오고 다음과 같은 세션으로 함수를 plustwo호출 할 수 있습니다 .addtwo

파이썬
파이썬
>>> 플러스투 가져오기
>>> x = plustwo.addtwo( 5 )
>>> 엑스
7

5. 연혁

  • 2023년 8월 2  : 최초 제출
  • 2023년 8월 4  : 고정 코드 라벨
  • 2023년 8월 9  : 다음에 대한 호출 추가PyFinalize

특허

이 문서는 관련 소스 코드 및 파일과 함께 The Code Project Open License(CPOL) 에 따라 사용이 허가되었습니다.

 

작성자
 
미국 미국

 

저는 20년 넘게 프로그래머, 엔지니어, 작가였습니다.

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
57 [python 인공지능] Deploy ML models with FastAPI, Docker, and Heroku | Tutorial 졸리운_곰 2025.07.08 467
56 [python 인공지능] [VSCode] VSCode에서 ipynb 파일을 HTML(PDF 등..)로 졸리운_곰 2025.05.27 289
55 [Python 인공지능] [파이썬을 이용한 한글 NLP] 03. 간단한 키워드 추출기 졸리운_곰 2025.01.29 459
54 [Python 인공지능] [ 한글 키워드 시각화 ] 파이썬 python 텍스트 마이닝 한글 ( 워드 클라우드 WordCloud, squrify 트리맵으로 빅데이터 마스터) file 졸리운_곰 2025.01.29 398
53 [Python 인공지능] 기계 학습의 A to Z : IPython notebook과 scikit-learn을 활용한 기계 학습 file 졸리운_곰 2024.08.10 523
52 [python] 인공지능 python : 한글 문서 자동 요약 - lexrank 졸리운_곰 2023.07.06 404
51 [python] 인공지능 katiehouse / django-scikit-learn-tutorial file 졸리운_곰 2023.06.03 664
50 [python] [Anaconda]가상환경 설치,삭제 file 졸리운_곰 2022.12.03 405
49 [python][머신러닝] Scikit-learn Tutorial: Machine Learning in Python file 졸리운_곰 2022.11.29 497
48 [python] 파이썬(sklearn) 사이킷런(sklearn) 기초 졸리운_곰 2022.08.20 321
47 [python] scikit-learn이란 file 졸리운_곰 2022.08.20 455
46 [anaconde3][python] Create environment for tensorflow 1.4 in Anaconda 3 졸리운_곰 2022.07.02 563
45 [python][인공지능] [TensorFlow] Anaconda 가상환경 이용하여 TensorFlow GPU 설치 졸리운_곰 2022.01.20 438
44 [Python 인공지능] TextRank 를 이용한 키워드 추출과 핵심 문장 추출 (구현과 실험) file 졸리운_곰 2021.11.22 597
43 [python][인공지능] FLASK를 이용하여 PYTHON에서 PYTORCH를 REST API로 배포하기 졸리운_곰 2021.03.20 364
42 [python 파이썬] Creating REST API for TensorFlow models file 졸리운_곰 2021.02.01 488
41 [python 파이썬 인공지능] Keras 모델을 REST API로 배포해보기 file 졸리운_곰 2021.02.01 411
40 [파이썬 머신러닝] Scikit-learn 기초 졸리운_곰 2020.01.31 579
39 파이썬으로 간단한 뉴럴 네트워크 만들기 How to Create a Simple Neural Network in Python file 졸리운_곰 2020.01.29 22636
38 Keras를 활용한 주식 가격 예측 file 졸리운_곰 2019.02.25 983
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED