Время на прочтение
11 мин
Количество просмотров 46K
DLL & Python
Недавно меня заинтересовала тема использования DLL из Python. Кроме того было интересно разобраться в их структуре, на тот случай, если придется менять исходники библиотек. После изучения различных ресурсов и примеров на эту тему, стало понятно, что применение динамических библиотек может сильно расширить возможности Python. Собственные цели были достигнуты, а чтобы опыт не был забыт, я решил подвести итог в виде статьи — структурировать свой знания и полезные источники, а заодно ещё лучше разобраться в данной теме.
Под катом вас ожидает статья с различными примерами, исходниками и пояснениями к ним.
Содержание
- Структура DLL
- DLL & Python
- Подключение DLL
- Типы данных в С и Python
- Аргументы функция и возвращаемые значения
- Своя DLL и ее использование
- Полезные ссылки:
Надеюсь из содержания немного станет понятнее какую часть нужно открыть, чтобы найти ответы на свои вопросы.
Структура DLL
DLL — Dynamic Link Library — динамическая подключаемая библиотека в операционной системе (ОС) Windows. Динамические библиотеки позволяют сделать архитектуру более модульной, уменьшить количество используемых ресурсов и упрощают модификацию системы. Основное отличие от .EXE файлов — функции, содержащиеся в DLL можно использовать по одной.
Учитывая, что статья не о самих библиотеках, лучше просто оставить здесь ссылку на довольно информативную статью от Microsoft: Что такое DLL?.
Для того, чтобы понять, как использовать динамические библиотеки, нужно вникнуть в их структуру.
DLL содержит набор различных функций, которые потом можно использовать по-отдельности. Но также есть возможность дополнительно указать функцию точки входа в библиотеку. Такая функция обычно имеет имя DllMain
и вызывается, когда процессы или потоки прикрепляются к DLL или отделяются от неё. Это можно использовать для инициализации различных структур данных или их уничтожения.
Рисунок 1 — Пустой template, предлагаемый Code Blocks для проекта DLL.
На рисунке 1 приведен шаблон, который предлагает Code Blocks, при выборе проекта типа DLL. В представленном шаблоне есть две функции:
#define DLL_EXPORT __declspec(dllexport) // обязательно определять функции,
// которые могут быть экспортированы из // библиотеки
void DLL_EXPORT SomeFunction(const LPCSTR sometext); // просто функция для примера, она вызывает вывод сообщения в окно
extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) //функция точки входа
Для начала стоит подробнее рассмотреть функциюDllMain
. Через нее ОС может уведомлять библиотеку о нескольких событиях (fdwReason):
-
DLL_PROCESS_ATTACH – подключение DLL. Процесс проецирования DLL на адресное пространство процесса. С этим значением DllMain вызывается всякий раз, когда какой-то процесс загружает библиотеку с явной или неявной компоновкой.
-
DLL_PROCESS_DETACH – отключение DLL от адресного пространства процесса. С этим значением DllMain вызывается при отключении библиотеки.
-
DLL_THREAD_ATTACH – создание процессом, подключившим DLL, нового потока. Зачем DLL знать о каких-то там потоках? А вот зачем, далеко не каждая динамическая библиотека может работать в многопоточной среде.
-
DLL_THREAD_DETACH – завершение потока, созданного процессом, подключившим DLL. Если динамическая библиотека создает для каждого потока свои «персональные» ресурсы (локальные переменные и буфера), то это уведомление позволяет их своевременно освобождать.
Опять же, в тему структуры DLL можно углубляться до бесконечности, там есть много различных нюансов, о которых немного изложено в этой статье.
У DllMain
не так много аргументов, самый важный fdwReason
уже рассмотрен выше, теперь о двух других:
- Аргумент lpvReserved указывает на способ подключения DLL:
- 0 — библиотека загружена с явной компоновкой.
- 1 — библиотека загружена с неявной компоновкой.
- Аргумент hinstDLL содержит описатель экземпляра DLL. Любому EXE- или DLL-модулю, загружаемому в адресное пространство процесса, присваивается уникальный описатель экземпляра.
О явной и неявной компоновке можно прочесть подробно в статье: Связывание исполняемого файла с библиотекой DLL.
В предложенном на рисунке 1 шаблоне есть функция SomeFunction
, которая может быть экспортирована из динамической библиотеки. Для того, чтобы это показать, при объявлении функции указывается __declspec(dllexport)
. Например, так:
#define DLL_EXPORT __declspec(dllexport)
void DLL_EXPORT SomeFunction(const LPCSTR sometext);
Функции, не объявленные таким образом, нельзя будет вызывать снаружи.
DLL & Python
Первым делом, расскажу, как подключать уже собранные DLL, затем, как вызывать из них функции и передавать аргументы, а уже после этого, постепенно доделаю шаблон из Code Blocks и приведу примеры работы с собственной DLL.
Подключение DLL
Основной библиотекой в Python для работы с типами данных, совместимыми с типами языка С является ctypes
. В документации на ctypes представлено много примеров, которым стоит уделить внимание.
Чтобы начать работать с DLL, необходимо подключить библиотеку к программе на Python. Сделать это можно тремя способами:
- cdll — загружает динамическую библиотеку и возвращает объект, а для использования функций DLL нужно будет просто обращаться к атрибутам этого объекта. Использует соглашение вызовов cdecl.
- windll — использует соглашение вызовов stdcall. В остальном идентична cdll.
- oledll — использует соглашение вызовов stdcall и предполагается, что функции возвращают код ошибки Windows HRESULT. Код ошибки используется для автоматического вызова исключения WindowsError.
Про соглашения о вызове функций.
Для первого примера будем использовать стандартную Windows DLL библиотеку, которая содержит всем известную функцию языка С — printf()
. Библиотека msvcrt.dll
находится в папке C:WINDOWSSystem32
.
Код Python:
from ctypes import *
lib = cdll.msvcrt # подключаем библиотеку msvcrt.dll
lib.printf(b"From dll with love!n") # вывод строки через стандартную printf
var_a = 31
lib.printf(b"Print int_a = %dn", var_a) # вывод переменной int
# printf("Print int_a = %dn", var_a); // аналог в С
Результат:
From dll with love!
Print int_a = 31
Можно использовать подключение библиотеки с помощью метода windll
либо oledll
, для данного кода разницы не будет, вывод не изменится.
Если речь не идет о стандартной библиотеке, то конечно следует использовать вызов с указанием пути на dll. В ctypes
для загрузки библиотек предусмотрен метод LoadLibrary
. Но есть еще более эффективный конструктор CDLL
, он заменяет конструкцию cdll.LoadLibrary
. В общем, ниже показано два примера вызова одной и той же библиотеки msvcrt.dll.
Код Python:
from ctypes import *
lib = cdll.LoadLibrary(r"C:WindowsSystem32msvcrt.dll")
lib.printf(b"From dll with love!n") # вывод строки через стандартную printf
lib_2 = CDLL(r"C:WindowsSystem32msvcrt.dll") # подключаем библиотеку msvcrt.dll
var_a = 31
lib_2.printf(b"Print int_a = %dn", var_a) # вывод переменной int
Иногда случается, что необходимо получить доступ к функции или атрибуту DLL, имя которого Python не «примет»… ну бывает. На этот случай имеется функции getattr(lib, attr_name)
. Данная функция принимает два аргумента: объект библиотеки и имя атрибута, а возвращает объект атрибута.
Код Python:
from ctypes import *
lib = cdll.LoadLibrary(r"C:WindowsSystem32msvcrt.dll")
var_c = 51
print_from_C = getattr(lib, "printf") # да, тут можно вписать даже "??2@YAPAXI@Z"
print_from_C(b"Print int_c = %dn", var_c)
Результат:
Print int_c = 51
Теперь становится понятно, как подключить библиотеку и использовать функции. Однако, не всегда в DLL нужно передавать простые строки или цифры. Бывают случаи, когда требуется передавать указатели на строки, переменные или структуры. Кроме того, функции могут и возвращать структуры, указатели и много другое.
Типы данных в С и Python
Модуль ctypes
предоставляет возможность использовать типы данных совместимые с типами в языке С. Ниже приведена таблица соответствия типов данных.
Таблица 1 — Соответствие типов данных языка Python и языка C, которое предоставляет модуль ctypes
.
Первое, что стоит попробовать — это использовать указатели, куда без них? Давайте напишем программу, где создадим строку и указатель на неё, а потом вызовем printf() для них:
Код:
from ctypes import *
lib = CDLL(r"C:WindowsSystem32msvcrt.dll")
printf = lib.printf # объект функции printf()
int_var = c_int(17) # переменная типа int из C
printf(b"int_var = %dn", int_var)
str_ = b"Hello, Worldn" # строка в Python
str_pt = c_char_p(str_) # указатель на строку
printf(str_pt)
print(str_pt)
print(str_pt.value) # str_pt - указатель на строку, значение можно получить с использованием атрибута value
Результат:
int_var = 17
Hello, World
c_char_p(2814054827168)
b'Hello, Worldn'
Если вы создали указатель, то разыменовать (получить доступ к значению, на которое он указывает) можно с использованием атрибута value
, пример выше.
Аргументы функций и возвращаемые значения
По умолчанию предполагается, что любая экспортируемая функция из динамической библиотеки возвращает тип int
. Другие возвращаемые типы можно указать при помощи атрибута restype
. При этом, чтобы указать типы аргументов функции можно воспользоваться атрибутом argtypes
.
Например, стандартная функция strcat
принимает два указателя на строки и возвращает один указатель на новую строку. Давайте попробуем ей воспользоваться.
char *strcat (char *destination, const char *append); // C функция для конкатонации (склеивания) строк
Код Python:
from ctypes import *
libc = CDLL(r"C:WindowsSystem32msvcrt.dll")
strcat = libc.strcat # получаем объект функции strcat
strcat.restype = c_char_p # показываем, что функция будет возвращать указатель на # строку
strcat.argtypes = [c_char_p, c_char_p] # показывает типы аргументов функции
str_1 = b"Hello,"
str_2 = b" Habr!"
str_pt = strcat(str_1, str_2) # вызываем стандартную функцию
print(str_pt)
Результат:
b'Hello, Habr!'
На этом закончим с примерами использования готовых DLL. Давайте попробуем применить знания о структуре DLL и модуле ctypes
для того, чтобы собрать и начать использовать собственную библиотеку.
Своя DLL и ее использование
Пример 1
Шаблон DLL уже был рассмотрен выше, а сейчас, когда дело дошло до написания своей DLL и работы с ней, выскочили первые и очевидные грабли — несовместимость разрядности DLL и Python. У меня на ПК установлен Python x64, оказалось, что как бы ни были DLL универсальны, разрядность DLL должна соответствовать разрядности Python. То есть, либо ставить компилятор x64 и Python x64, либо и то и то x32. Хорошо, что это не сложно сделать.
Ниже привожу код шаблона DLL, в который добавил вывод строки при подключении библиотеки, а также небольшой разбор и вывод аргументов, с которыми вызвалась DllMain
. В примере можно понаблюдать, какие участки кода библиотеки вызываются и когда это происходит.
Код DLL на С:
// a sample exported function
void __declspec(dllexport) SomeFunction(const LPCSTR sometext)
{
MessageBoxA(0, sometext, "DLL Message", MB_OK | MB_ICONINFORMATION);
}
extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
printf("Load DLL in Pythonn");
printf("HINSTANCE = %pn",hinstDLL); // Вывод описателя экземпляра DLL
if (lpvReserved) // Определение способа загрузки
printf("DLL loaded with implicit layoutn");
else
printf("DLL loaded with explicit layoutn");
return 1; // Успешная инициализация
case DLL_PROCESS_DETACH:
printf("DETACH DLLn");
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE; // succesful
}
Код Python:
from ctypes import *
lib_dll = cdll.LoadLibrary("DLL_example.dll") # подключаю свою DLL
str_ = b'Hello, Habr!'
p_str = c_char_p(str_) # получаю указатель на строку str_
lib_dll.SomeFunction(p_str) # вызываю SomeFunction из DLL
Функция SomeFunction
получает указатель на строку и выводит её в окно. На рисунке ниже показана работа программы.
Рисунок 2 — Демонстрация работы шаблона библиотеки из Code Blocks.
Все действия происходящие в кейсе DLL_PROCESS_ATTACH
, код которого приведен ниже, вызываются лишь одной строкой в Python коде:
lib_dll = cdll.LoadLibrary("DLL_example.dll") # подключение библиотеки
Рисунок 3 — Действия происходящие при подключении DLL.
Пример 2
Чтобы подвести итог по использованию DLL библиотек из Python, приведу пример, в котором есть начальная инициализация параметров и передача новых через указатели на строки и структуры данных. Этот код дает понять, как написать аналог структуры С в Python. Ниже привожу код main.c
, man.h
и main.py
.
Код DLL на С:
main.h
#ifndef __MAIN_H__
#define __MAIN_H__
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define DLL_EXPORT __declspec(dllexport) // обязательно определять функции,
// которые могут быть экспортированы из // библиотеки
#ifdef __cplusplus
extern "C"
{
#endif
struct Passport{
char* name;
char* surname;
int var;
};
void DLL_EXPORT SetName(char* new_name);
void DLL_EXPORT SetSurname(char* new_surname);
void DLL_EXPORT SetPassport(Passport* new_passport);
void DLL_EXPORT GetPassport(void);
#ifdef __cplusplus
}
#endif
#endif // __MAIN_H__
В коде main.h
определена структура Passport с тремя полями: два указателя и целочисленная переменная. Кроме того, четыре функции объявлены, как экспортируемые.
Код DLL на С:
main.c
#include "main.h"
#define SIZE_BUF 20
struct Passport passport; // объявляем переменную passport типа Passport
// Функция установки имени
void DLL_EXPORT SetName(char* new_name)
{
printf("SetNamen");
strcpy(passport.name, new_name);
}
// Функция установки фамилии
void DLL_EXPORT SetSurname(char* new_surname)
{
printf("SetSurnamen");
strcpy(passport.surname, new_surname);
}
// Функция установки полей структуры.
// На вход принимает указатель на структуру
void DLL_EXPORT SetPassport(Passport* new_passport)
{
printf("SetPassportn");
strcpy(passport.name, new_passport->name);
strcpy(passport.surname, new_passport->surname);
passport.var = new_passport->var;
}
// Вывести в консоль данные структуры
void DLL_EXPORT GetPassport(void)
{
printf("GetPassport: %s | %s | %dn", passport.name, passport.surname, passport.var);
}
extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
printf("Load DLL in Pythonn");
passport.name = (char*)malloc(SIZE_BUF * sizeof(char)); // выделение памяти
passport.surname = (char*)malloc(SIZE_BUF * sizeof(char)); // выделение памяти
passport.var = 17; // начальная инициализация переменной
SetName("Default"); // начальная инициализация буфера имени
SetSurname("Passport"); // начальная инициализация буфера фамилии
return 1;
case DLL_PROCESS_DETACH:
free (passport.name); // Освобождение памяти
free (passport.surname); // Освобождение памяти
printf("DETACH DLLn");
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE; // succesful
}
Внутри кейса DLL_PROCESS_ATTACH
происходит выделение памяти под строки и начальная инициализация полей структуры. Выше DllMain
определены функции:
-
GetPassport — вывод полей структуры
passport
в консоль. -
*SetName(char new_name)** — установка поля
name
структурыpassport
. -
*SetSurname(char new_surname)** — установка поля
surname
структурыpassport
. -
*SetPassport(Passport new_passport)** — установка всех полей структуры
passport
. Принимает в качестве аргумента указатель на структуру с новыми полями.
Теперь можно подключить библиотеку в Python.
Код на Python
from ctypes import *
class Passport(Structure): # класс, который соответствует структуре Passport
_fields_ = [("name", c_char_p), # из файла main.h
("surname", c_char_p),
("var", c_int)]
lib_dll = cdll.LoadLibrary("DLL_example.dll") # подключаю свою DLL
lib_dll.SetPassport.argtypes = [POINTER(Passport)] # указываем, тип аргумента функции
lib_dll.GetPassport() # вывод в консоль структуры
lib_dll.SetName(c_char_p(b"Yury"))
lib_dll.SetSurname(c_char_p(b"Orlov"))
lib_dll.GetPassport() # вывод в консоль структуры
name = str.encode(("Vasiliy")) # первый вариант получения указателя на байтовую строку
surname = c_char_p((b'Pupkin')) # второй вариант получения указателя на байтовую строку
passport = Passport(name, surname, 34) # создаем объект структуры Passport
lib_dll.SetPassport(pointer(passport)) # передача структуры в функцию в DLL
lib_dll.GetPassport() # вывод в консоль структуры
В коде выше многое уже знакомо, кроме создания структуры аналогичной той, которая объявлена в DLL и передачи указателя на эту структуру из Python в DLL.
Результат:
Load DLL in Python
SetName
SetSurname
GetPassport: Default | Passport | 17
SetName
SetSurname
GetPassport: Yury | Orlov | 17
SetPassport
GetPassport: Vasiliy | Pupkin | 34
DETACH DLL
P.S: Думаю, что примеры и объяснения из статьи помогут вам быстро начать использовать DLL библиотеки из Python. Ну а если вы не смогли найти ответы на свои вопросы то может помогут ссылки ниже. Если у кого-то будут вопросы — постараюсь ответить, если будут замечания — постараюсь исправить. Спасибо, что дочитали!
Полезные ссылки:
- Документации ctypes — много примеров
- Что такое DLL? — много и полно о dll.
- [C/C++ из Python (ctypes)](C/C++ из Python (ctypes)) — хорошая статья.
- Передача двумерных списков из python в DLL
- Связывание исполняемого файла с библиотекой DLL
- Github с dll «Hello-world» и её кодом — можно воспользоваться для тестирования.
- Что такое TCHAR, WCHAR, LPSTR, LPWSTR,LPCTSTR — о типах данных.
- Динамические библиотеки для гурманов — статья с большим количеством интересных нюансов.
To expand on the answer by Nick ODell
You must be on Windows for DLLs to work, they are not portable.
However the code below is cross platform and all platforms support run-times so this can be re-compiled for each platform you need it to work on.
Python does not (yet) provide an easy tool to create a dll, however you can do it in C/C++
First you will need a compiler (Windows does not have one by default) notably Cygwin, MinGW or Visual Studio.
A basic knowledge of C is also necessary (since we will be coding mainly in C).
You will also need to include the necessary headers, I will skip this so it does not become horribly long, and will assume everything is set up correctly.
For this demonstration I will print a traditional hello world:
Python code we will be converting to a DLL:
def foo(): print("hello world")
C code:
#include "Python.h" // Includes everything to use the Python-C API
int foo(void); // Declare foo
int foo(void) { // Name of our function in our DLL
Py_Initialize(); // Initialise Python
PyRun_SimpleString("print('hello world')"); // Run the Python commands
return 0; // Finish execution
}
Here is the tutorial for embedding Python. There are a few extra things that should be added here, but for brevity I have left those out.
Compile it and you should have a DLL.
That is not all. You will need to distribute whatever dependencies are needed, that will mean the python36.dll
run-time and some other components to run the Python script.
My C coding is not perfect, so if anyone can spot any improvements please comment and I will do my best to fix the it.
It might also be possible in C# from this answer How do I call a specific Method from a Python Script in C#?, since C# can create DLLs, and you can call Python functions from C#.
To expand on the answer by Nick ODell
You must be on Windows for DLLs to work, they are not portable.
However the code below is cross platform and all platforms support run-times so this can be re-compiled for each platform you need it to work on.
Python does not (yet) provide an easy tool to create a dll, however you can do it in C/C++
First you will need a compiler (Windows does not have one by default) notably Cygwin, MinGW or Visual Studio.
A basic knowledge of C is also necessary (since we will be coding mainly in C).
You will also need to include the necessary headers, I will skip this so it does not become horribly long, and will assume everything is set up correctly.
For this demonstration I will print a traditional hello world:
Python code we will be converting to a DLL:
def foo(): print("hello world")
C code:
#include "Python.h" // Includes everything to use the Python-C API
int foo(void); // Declare foo
int foo(void) { // Name of our function in our DLL
Py_Initialize(); // Initialise Python
PyRun_SimpleString("print('hello world')"); // Run the Python commands
return 0; // Finish execution
}
Here is the tutorial for embedding Python. There are a few extra things that should be added here, but for brevity I have left those out.
Compile it and you should have a DLL.
That is not all. You will need to distribute whatever dependencies are needed, that will mean the python36.dll
run-time and some other components to run the Python script.
My C coding is not perfect, so if anyone can spot any improvements please comment and I will do my best to fix the it.
It might also be possible in C# from this answer How do I call a specific Method from a Python Script in C#?, since C# can create DLLs, and you can call Python functions from C#.
To expand on the answer by Nick ODell
You must be on Windows for DLLs to work, they are not portable.
However the code below is cross platform and all platforms support run-times so this can be re-compiled for each platform you need it to work on.
Python does not (yet) provide an easy tool to create a dll, however you can do it in C/C++
First you will need a compiler (Windows does not have one by default) notably Cygwin, MinGW or Visual Studio.
A basic knowledge of C is also necessary (since we will be coding mainly in C).
You will also need to include the necessary headers, I will skip this so it does not become horribly long, and will assume everything is set up correctly.
For this demonstration I will print a traditional hello world:
Python code we will be converting to a DLL:
def foo(): print("hello world")
C code:
#include "Python.h" // Includes everything to use the Python-C API
int foo(void); // Declare foo
int foo(void) { // Name of our function in our DLL
Py_Initialize(); // Initialise Python
PyRun_SimpleString("print('hello world')"); // Run the Python commands
return 0; // Finish execution
}
Here is the tutorial for embedding Python. There are a few extra things that should be added here, but for brevity I have left those out.
Compile it and you should have a DLL.
That is not all. You will need to distribute whatever dependencies are needed, that will mean the python36.dll
run-time and some other components to run the Python script.
My C coding is not perfect, so if anyone can spot any improvements please comment and I will do my best to fix the it.
It might also be possible in C# from this answer How do I call a specific Method from a Python Script in C#?, since C# can create DLLs, and you can call Python functions from C#.
142 / 26 / 4 Регистрация: 06.05.2019 Сообщений: 1,680 Записей в блоге: 4 |
|
1 |
|
25.02.2020, 01:13. Показов 5944. Ответов 23
Если возможно что можно почитать и изучить, дайте информацию на такие ресурсы?
0 |
Programming Эксперт 94731 / 64177 / 26122 Регистрация: 12.04.2006 Сообщений: 116,782 |
25.02.2020, 01:13 |
23 |
4606 / 2027 / 359 Регистрация: 17.03.2012 Сообщений: 10,084 Записей в блоге: 6 |
|
25.02.2020, 13:20 |
2 |
Не знаю, что такое mql. Добавлено через 21 секунду
1 |
142 / 26 / 4 Регистрация: 06.05.2019 Сообщений: 1,680 Записей в блоге: 4 |
|
25.02.2020, 15:29 [ТС] |
3 |
Для длл-ок следует использовать С++ Есть нужда в обработке имён функций и создании массивов, С++ не обладает такими гибкими возможностями, спасибо за советы.
0 |
4606 / 2027 / 359 Регистрация: 17.03.2012 Сообщений: 10,084 Записей в блоге: 6 |
|
25.02.2020, 17:16 |
4 |
Nexi99, не понял, что за обработка имён функций имеется в виду, но всё равно это не отменяет моего замечания. Если у вас большое приложение на плюсах и надо небольшой кусочек вынести в питон, то используется Python embedding. Вот это уже да, штатная операция.
0 |
142 / 26 / 4 Регистрация: 06.05.2019 Сообщений: 1,680 Записей в блоге: 4 |
|
25.02.2020, 19:01 [ТС] |
5 |
Python embedding Спасибо за информацию, если доживу то буду это всё использовать.
0 |
142 / 26 / 4 Регистрация: 06.05.2019 Сообщений: 1,680 Записей в блоге: 4 |
|
14.04.2020, 19:07 [ТС] |
6 |
Для С++ можно, но на сишной стороне надо будет использовать Python.h, т. е. специально адаптировать сишную часть. Если адаптировать Python.h на сишной стороне, то этот код откомпилируется и будет работать напрямую с процессором как стандартный сишный код или он так и останется текстом и будет происходить постоянная трансляция между Python и с++?
0 |
4606 / 2027 / 359 Регистрация: 17.03.2012 Сообщений: 10,084 Записей в блоге: 6 |
|
15.04.2020, 10:50 |
7 |
Адаптировать Python.h не надо, он поставляется разработчиками питона. Адаптировать надо вашу сишную часть, чтобы она использовала Python.h.
1 |
142 / 26 / 4 Регистрация: 06.05.2019 Сообщений: 1,680 Записей в блоге: 4 |
|
15.04.2020, 11:47 [ТС] |
8 |
Адаптировать надо вашу сишную часть, чтобы она использовала Python.h. Всё понятно спасибо.
0 |
4606 / 2027 / 359 Регистрация: 17.03.2012 Сообщений: 10,084 Записей в блоге: 6 |
|
15.04.2020, 13:22 |
9 |
Nexi99, питоновский код «транслируется» в штатном порядке, как питоновский. (На самом деле он не транслируется, но для простоты скажем так.)
0 |
Просто Лис 4862 / 3180 / 997 Регистрация: 17.05.2012 Сообщений: 9,288 Записей в блоге: 9 |
|
15.04.2020, 14:21 |
10 |
mql. mySQL же
Просто питоновский код сможет вызывать ваш сишный. Человеку наоборот надо из С++ вызывать питон. ТС, там по факту вшивается интерпретатор питона. Пример: На сколько сложно перевести код Python на Си?
0 |
Garry Galler 5403 / 3827 / 1214 Регистрация: 28.10.2013 Сообщений: 9,554 Записей в блоге: 1 |
||||
15.04.2020, 14:25 |
11 |
|||
mySQL же Не а. Это трейдерский язык программирования a-la Си, только проще.
Человеку наоборот надо из С++ вызывать питон. Вот только ТС этого не понимает. Он думает что можно написать на Python скрипт, превратить его в обычную dll (не Python pyd) и потом пользоваться в С++.
0 |
Просто Лис 4862 / 3180 / 997 Регистрация: 17.05.2012 Сообщений: 9,288 Записей в блоге: 9 |
|
15.04.2020, 14:30 |
12 |
Наверное, можно и dll-ку скомпилить. Только она будет работать со скоростью питона, то есть никак.
0 |
142 / 26 / 4 Регистрация: 06.05.2019 Сообщений: 1,680 Записей в блоге: 4 |
|
15.04.2020, 17:57 [ТС] |
13 |
Вот только ТС этого не понимает. Он думает что можно написать на Python скрипт, превратить его в обычную dll (не Python pyd) и потом пользоваться в С++. Я уже разобрался благодаря вам конечно, что скомпилировать Пион не получиться. Добавлено через 7 минут
mql. WinAPI Добавлено через 2 часа 11 минут
Для длл-ок следует использовать С++ и прочий натив Скажите а как читаются dll библиотеки(например сишные), подключенные к основной программе как бинарные файлы или как скрипты (происходит постоянный поиск указанной функции), ведь по сути динамическая dll подключенная к основной программе не компилируется а ошибки вылетают только тогда когда сама программа запущена а не в момент компиляции, возникает много вопросов как это всё работает.
0 |
Просто Лис 4862 / 3180 / 997 Регистрация: 17.05.2012 Сообщений: 9,288 Записей в блоге: 9 |
|
15.04.2020, 18:04 |
14 |
как читаются dll библиотеки(например сишные), Библиотека — она есть библиотека. Есть заголовки функций, в dll — сама скомпилированная функция. И при вызове функции можно уронить программу.
0 |
4606 / 2027 / 359 Регистрация: 17.03.2012 Сообщений: 10,084 Записей в блоге: 6 |
|
15.04.2020, 19:03 |
15 |
Скажите а как читаются dll библиотеки(например сишные), подключенные к основной программе как бинарные файлы или как скрипты Что из себя представляет «основная программа»? Бинарные файлы и скрипты — это большая разница.
0 |
1550 / 875 / 179 Регистрация: 05.12.2015 Сообщений: 2,555 |
|
15.04.2020, 19:41 |
16 |
Nexi99, У меня к вам пара вопросов.
0 |
142 / 26 / 4 Регистрация: 06.05.2019 Сообщений: 1,680 Записей в блоге: 4 |
|
15.04.2020, 20:37 [ТС] |
17 |
Вы можете написать компилятор, или хотя бы транслятор своего языка по типу этого mql? Могу писать но у меня жизни не хватит на это эти оболочки и весь функционал долго строится. Но почему-то исходного кода от mql4 нет, как же мне модифицировать его, только писать свой компилятор или библиотеки. Кто неасилил написание бота я? Это дело большого времени, печи да и всё в чём проблема. Об этом умалчивают и очень хорошо. Кто со мной чем поделился, если бы поделился меня бы здесь не было. Я писал что они тупее, может и писал может и тупее что изменилось. Я пишу своего робота влаживая(очень большую) частицу себя. Возникает вопрос а языки программирования тоже ведь для маркетинга придумали правильно.
0 |
1550 / 875 / 179 Регистрация: 05.12.2015 Сообщений: 2,555 |
|
15.04.2020, 21:21 |
18 |
Могу писать но у меня жизни не хватит на это эти оболочки и весь функционал долго строится. Ну и? Они, тупые, писали это чтоб ты обогатился? Сами-то они без тебя, конечно, грамотного робота не напишут. Вот на то, на что у тебя жизни не хватит у них времени хватило, а на робота… ну тупые они, без тебя никак.
Об этом умалчивают и очень хорошо Да, это тайна за семью замками. Никто не знает. Только ты. Всех остальных в гугле забанили. Поэтому ты пришел на форум с тривиальным вопросом. Вот бы мне нагуглить как создать торгового робота и обогатиться за три секунды. Но, видишь ли, я, наверное, тупой. Вот, написать любой другой софт, где нужна определенная квалификация, я могу. А торгового робота… ну куда мне. Это только ты можешь.
0 |
142 / 26 / 4 Регистрация: 06.05.2019 Сообщений: 1,680 Записей в блоге: 4 |
|
15.04.2020, 22:14 [ТС] |
19 |
Поэтому ты пришел на форум с тривиальным вопросом. Вот бы мне нагуглить как создать торгового робота и обогатиться за три секунды. По поводу тупой не тупой скажу что я идейный человек.
0 |
1550 / 875 / 179 Регистрация: 05.12.2015 Сообщений: 2,555 |
|
15.04.2020, 23:00 |
20 |
Где я писал о том что можно написать робота за 3 с., а также о том как его написать, всему учился сам. Ни в одной из моих тем не было упоминания о подобном. Это очень простой софт. Придумать что-то проще сложно.
Уже 3 года я топчусь и ушёл не очень далеко. Да. Потому что идти некуда. Это тупик. Проще «заработать» играя в казино.
И вообще если хотите писать подобные сообщения пишите мне в личку а не здесь, это не совсем корректно. Это вполне корректно. Я писал о явлении торговых роботов как таковом. Может быть мои посты спасут кого-нибудь, в чью голову придет такая идея, но кто еще способен здраво ее осмыслить.
0 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
15.04.2020, 23:00 |
20 |
Рука учит вас упаковать программу Python в DLL
Тип данных Python и Тип данных C выглядит как отношение «однонаправления« однонаправленно », кроме того, из-за Python он реализован языком C, поскольку Python реализуется языком C, поэтому функция между типом данных Python Операция также необходима для соответствия языку C. Итак, есть ли возможным «автоматическим» для замены, поверните код Python непосредственно в C-код? Ответ да, это главная проблема Cython.
В этом руководстве представит, как сделать Python Code в DLL для программ C / C ++ для программ C / C ++ с Cython.
Компилятор окружающей среды
- Python 3 или Python 2
- Visual Studio
- JetBrains PyCharm
Установите Cython
Cython — это язык, который сочетает в себе грамматику Python и C, который можно просто дать Python со статическим типом синтаксиса.
Если Cython был установлен, вы можете пропустить этот шаг. Установка Cython Использовать easy_install, Python 2.7.9 или более поставлена с Easy_install. Завершение в командной строке Visual Studio (обратите внимание, что версия Python использует 32 бита или 64-разрядную командную строку Visual Studio, можно запустить с привилегиями администратора):
easy_install -U cython
Компиляция с Цифоном
В новом проекте в Pycharm создайте файл PY: Great_module.py, введите следующее:
def str_add(str1, str2):
return int(str1) + int(str2)
Это функция, которая преобразует строку для суммирования INT. Чтобы сделать эту функцию можно скомпилировать Cython, вам нужно создать новый файл run.pyx и добавить следующее:
cdef public int str_add(const char* str1,const char* str2):
return int(str1) + int(str2)
CDEF и публикация — это все ключевые слова Cython, которые могут помочь функциям, которые могут быть вызваны внешними вызовами. Затем используйте следующую команду в Pycharm, чтобы генерировать два файла в Run.h и run.c.
cython run.pxy
Cython — это функция динамического типа, которая поддерживает Python. Если последующие шаги используют VS Command Line Compilation, также могут генерировать DLL, но я не знаю, почему я не могу извлечь функциональные адреса в DLL, поэтому равномерный тип, все параметры , и значения возврата используют ключевые слова статического типа Cython, чтобы указать типы данных.
Компилируйте динамическую библиотеку ссылок по VS
После получения .c и .h файл нам нужно создать проект VS DLL для него. Откройте VS-программное обеспечение, создайте новый проект Win32, в котором DLL выбора типа приложения и дополнительные параметры выбирают пустой проект. Скопируйте файл просто .c и .h к папке кода хранения проекта и добавьте его в проект. Добавьте пустую DLLMain.cpp в проекте и добавьте следующий код:
#include <Python.h>
#include <Windows.h>
#include "run.h"
extern "C"
{
__declspec(dllexport) int __stdcall _str_add(const char * a, const char * b)
{
return str_add(a, b);
}
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
Py_Initialize();
// DLL вызывается, когда она инициализирована, что является методом записи Python3, и Python2 изменяется, initrun (). Смотрите сгенерированный run.h
PyInit_run();
break;
case DLL_PROCESS_DETACH:
Py_Finalize();
break;
}
return TRUE;
}
Щелкните правой кнопкой мыши на элементах, атрибутах, введите вкладку каталога VC ++. Добавить Python, включая «C: Programpfiles python36 включать». Добавьте Python’s Lib в библиотеку, такую как «C: Program Files python36 libs». Обратите внимание, что выбрана сборная версия, а платформа X64 или платформа X32 выбирается в соответствии с версией Python. Файлы DLL могут быть получены после компиляции.
Динамический звонок DLL
Установите другой проект для проверки только что сгенерированной DLL. Откройте VS New Win32 Console Console и добавьте следующий код:
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;
int main()
{
// вызовите тест DLL
typedef int(*pAdd)(const char * a, const char * b);
HINSTANCE hDLL = LoadLibrary(_T("MyDLL.dll"));
cout << "hDLL:" << hDLL << endl;
if (hDLL)
{
/ / Получить адрес функции, которая должна быть вызвана в DLL
pAdd pFun = (pAdd)GetProcAddress(hDLL, "_str_add");
cout << "pFun:" << pFun << endl;
const char* stra= "12";
const char* strb = "22";
if (pFun)
{
int i = pFun(stra, strb);
cout << "i = " << i << endl;
}
}
system("pause");
return 0;
}
Согласно выделению DLL Platform X86 или X64, выходной результат «I = 34» может быть получен после компиляции выпуска.
Добавить
- После получения файлов .H и .C через Cython он может быть скомпилирован командой VS команда CL. Этот метод поддерживает динамический тип данных Python. Вам необходимо обратить внимание на выбора платформы X86 / X64 и привилегии администратора при компиляции. Но я не могу назвать правильно после успешной компиляции, и я до сих пор не знаю конкретных причин.
- Компиляция под Linux будет более удобным, поскольку Linux Native поддерживает Python и имеет компилятор C / C ++, конфигурация окружающей среды будет легче.
Reference
- C / C ++ и Python смешанное программирование
- C ++ Регулирует ошибку приглашения скрипта Python Script LNK2001: невозможно разрешить внешний символ __imp_Py_initialize и другие ошибки
- C ++ DLL Динамический вызов (явный)
What is a DLL file?
A library is a collection of non-volatile resources that are used for software development. In this tutorial, we are going to create our own dynamic link library(DLL) using c#. A DLL is a library used on Microsoft platforms that contains code and data that can be used by more than one program at the same time. If you open the program information of most applications installed on Microsoft Windows you will notice DLL files. These DLL files store different functionalities for the application. Some of the advantages of DLL files are:
- Code reuse
- Efficient memory usage
- Reduced disk space
- Fast loading of applications
Making a DLL file
In this tutorial, we are going to make a simple calculator library that does addition, subtraction, multiplication, and division using C# in Visual Studio.
Create the project (library) in Visual Studio as follows
- Create new project
- Select C# Class Library (.Net Standard)
- Project name -> MyCalculator
The code for your library
Add the following code:
using System;
namespace MyCalculator
{
public class Calculator
{
//Our addition function
public double add(double num_one, double num_two)
{
return num_one + num_two;
}
//Our subtraction function
public double subtract(double num_one, double num_two)
{
return num_one - num_two;
}
//Our multiplication function
public double multiply(double num_one, double num_two)
{
return num_one * num_two;
}
//Our division function
public double divide(double num_one, double num_two)
{
return num_one / num_two;
}
}
}
Enter fullscreen mode
Exit fullscreen mode
Building your library project
Click on: Build -> Build Solution
Locating your Calculator Library
Your MyCalculator.dll
is located in:
Your project folder -> MyCalculator -> MyCalculator -> bin -> debug
Using the DLL file in .Net
We are going to use our Calculator library MyCalculator.dll
in a simple C# application.
Create a c# console application in Visual Studio as follows:
- File -> New -> Project
- Select: C# Console App
- Project name: MyProject
Importing our calculator library
- Copy
MyCalculator.dll
from: Your library project folder -> MyCalculator -> MyCalculator -> bin -> debug - Paste
MyCalculator.dll
to Your project folder -> MyProject -> MyProject -> bin -> debug - Add reference to your dll file:
In solution explorer: Under MyProject -> Right click MyProject
-> add -> Project reference - Browse: Go to (Your project folder -> MyCalculator -> MyCalculator -> bin -> debug ->
MyCalculator.dll
- Click add
The code for your project (MyProject)
Edit your code as follows:
using System;
using MyCalculator; // importing our calculator library
namespace MyProject
{
class Program
{
static void Main(string[] args)
{
Calculator calc = new Calculator(); //Our Acalculator class object
Console.WriteLine("Addition: "+calc.add(3, 2));
Console.WriteLine("Subtraction: " + calc.subtract(3, 2));
Console.WriteLine("Multiplication: " + calc.multiply(3, 2));
Console.WriteLine("Division: " + calc.divide(3, 2));
}
}
}
Enter fullscreen mode
Exit fullscreen mode
Using the DLL file in Python
Install pythonnet
pip install pythonnet
Enter fullscreen mode
Exit fullscreen mode
Python code
import clr #import clr from pythonnet
#load our dll file(mine is in my C:\ folder)
clr.AddReference("C:\MyCalculator.dll")
#import our calculator class from Our C# namespace MyCalculator
from MyCalculator import Calculator
calc = Calculator() #create our Calculator object
#calling our methoths and printing
print("Addition: "+str(calc.add(3, 2)))
print("Subtraction: "+str(calc.subtract(3, 2)))
print("Multiplication: "+str(calc.multiply(3, 2)))
print("Division: "+str(calc.divide(3, 2)))
Enter fullscreen mode
Exit fullscreen mode