Как использовать DLL, которая возвращает указатель массива в Python? - PullRequest
0 голосов
/ 09 октября 2019

Я пытаюсь получить массив в питоническом формате [numpy или list] из DLL, написанной на c # / c ++. Эта DLL выдает указатель на память, а не оцениваемый массив. Как я могу получить быстрый доступ к памяти (я написал DLL для ускорения кода)?

Я использовал модуль pythonnet, и мне удалось получить указатель памяти как, но я не могу извлечьуказатель памяти в виде целого или двоичного числа, а затем получить данные выходного вектора.

Здесь код Python:

import numpy as np
import clr
clr.AddReference(R'...\PyDLL.dll')  
from PyDLL import StringLibrary

my_instance = StringLibrary()

x = my_instance.arrayShift(np.array([1,2,3,4,5,6,7,8,9,0]).reshape(-1))

А затем код C #

namespace PyDLL
{
    public class StringLibrary
    {
        public static double[] arrayShift(double[] array)
        {
            int b = array.Length;
            double[] newArray = new double[b];

            for(int i=0; i<b; i++)
            {
                newArray[i] = array[b-i-1];
            }

            return newArray;
        }
    }
}

Я ожидаю, что выходной x в python является списком или массивом np, а теперь это объект System.Double [].

ожидаемый выходной x равен [0,9,8,7,6,5,4,3,2,1]

Спасибо за любую помощь

1 Ответ

1 голос
/ 11 октября 2019

После многих попыток и исследований мне удалось решить проблему следующим образом:

Cpp часть:

Open Visual Studio,затем создайте новый проект (Dynamic-Link Library). Назовите проект, добавьте в него новый файл (файл заголовка) и присвойте ему то же имя. Вставьте следующий код в заголовок:

// headerName.h - Contains declarations of math functions
#pragma once
#ifdef HEADERNAME_EXPORTS
#define HEADERNAME_API __declspec(dllexport)
#else
#define HEADERNAME_API __declspec(dllimport)
#endif

// Define the functions that will be called using the DLL
extern "C" HEADERNAME_API void funName1(...);
extern "C" HEADERNAME_API void funName2(...);
extern "C" HEADERNAME_API void funName3(...);
...;

В папке «Исходные файлы» добавьте новый файл с расширением .cpp (вызовите его с тем же именем, что и у проекта), затем напишите функцию в этомФайл .cpp. Вот пример кода:

#include "pch.h" // use stdafx.h in Visual Studio 2017 and earlier  COMPULSORY TO ADD
#include "HEADERNAME.h" // COMPULSORY TO ADD
#include lib#1
#include lib#2
#include lib#3
...
using namespace std;

void funName1(...)
{
    ...
}
void funName2(...)
{
    ...
}
void funName3(...)
{
    ...
}

Чтобы иметь возможность передавать массивы между python и c ++, в моем решении использование указателей необходимо, и возврат не должен использоваться. Выходная переменная передается как входная переменная, инициализируется в python, используя указатель. В DLL ячейки памяти выходных переменных переписываются, и, таким образом, когда DLL завершает функцию, вывод вычисляется и уже может использоваться python без возврата. Вот пример того, как написать функцию, используя указатели для входных и выходных массивов:

void funName(double* inputArray_pointer, double* outputArray_pointer, int extraVariable)
{
    double inner_var = 100;
    for (int i = 0; i < extraVariable; i++)
    {
        inner_var = min(inner_var, *(inputArray_pointer+i));
        *(outputArray_pointer + i) = inner_var;
    }
}

Затем перестройте DLL.

Python part

Чтобы правильно использовать DLL в коде Python, необходимо импортировать модули 'ctypes' и 'numpy'. Ниже приведен пример кода Python (он будет использовать пример библиотеки DLL точки (9)):

import numpy as np
import ctypes

cpp_fun = ctypes.CDLL(R'pathToDll/DLLname.dll')  

# Define the types of the arguments of the DLL (pointer, int, double, ecc)
cpp_fun.funName.argtypes = [np.ctypeslib.ndpointer(),
                            np.ctypeslib.ndpointer(),
                            ctypes.c_int]

# Allocate or define the input variables using numpy or the standard scalar of python (int, float, ecc..)
inputArray = np.array([0,1,2,3,4,5,6,7,8,9,...,1000]).reshape(-1).astype('f8')
outputArray = np.zeros([inputArray.shape[0]])astype('f8')
extraVariable = inputArray.shape[0]
cpp_fun.funName(inputArray, outputArray, extraVariable)

При этом в переменной 'outputArray' мы найдем результат вычислений, выполненных внутриDLL как структура массива np.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...