GOOGLE ADS

domingo, 17 de abril de 2022

ctypes asignan más memoria a la pila

Tengo un c-dll al que llamo desde python. La salida del dll es bastante grande y sospecho que esto causa un error

OSError: exception: stack overflow

Estoy bastante seguro de que el problema es el tamaño de la salida (aproximadamente 4x25x720 dobles). Reducir el tamaño de la salida (que no quiero hacer) hace que el error desaparezca.

En C#, puedo solucionar este problema asignando más memoria al subproceso de llamada, es decir,

thread = new Thread(() => calculate(ptr_in, ptr_out), 20000000); 

¿Es posible hacer algo similar con ctypes?

Este NO es el problema publicado aquí Ctypes: OSError:Exception: stack overflow.

EDITAR

Reflexionando sobre el problema, no creo que el problema sea el tamaño de la salida, sino el espacio que necesita el dll real. Es decir c_out inner_out, definido en ctypes_test.c. De todos modos, el problema sigue siendo el mismo.

En CI definir un dll de pruebadll_ctypes_test

ctypes_testT.h

#pragma once
#define N_ELEMENTS 1000
#define N_ARRAYS 50
typedef struct
{
double var_0;
double var_1;
double var_2;
double var_3;
double var_4;
double var_5;
double var_6;
double var_7;
double var_8;
double var_9;
} element;
typedef struct
{
int n_elements;
element elements[N_ELEMENTS];
} arr;
typedef struct
{
int n_arrays;
arr arrays[N_ARRAYS];
} c_out;

ctypes_test.c

#include "ctypes_testT.h"
__declspec(dllexport) void _stdcall dll_ctypes_test(double in, c_out *out)
{
c_out inner_out;
//Some caluclations on inner_out
//Wrap values of inner arr to out
}

Y el código Python

import ctypes
N_ELEMENTS = 1000
N_ARRAYS = 50
class element(ctypes.Structure):
_fields_ = [('var_0', ctypes.c_double),
('var_1', ctypes.c_double),
('var_2', ctypes.c_double),
('var_3', ctypes.c_double),
('var_4', ctypes.c_double),
('var_5', ctypes.c_double),
('var_6', ctypes.c_double),
('var_7', ctypes.c_double),
('var_8', ctypes.c_double),
('var_9', ctypes.c_double)]
class arr(ctypes.Structure):
_fields_ = [('n_elements', ctypes.c_int),
('elements', element * N_ELEMENTS)]
class c_out(ctypes.Structure):
_fields_ = [('n_arrays', ctypes.c_int),
('arrays', arr * N_ARRAYS)]
dll = ctypes.WinDLL(r'C:\repos\ctypes_test\x64\Debug\ctypes_test.dll')
dll.dll_ctypes_test.argtypes = [ctypes.c_double, ctypes.POINTER(c_out)]
dll.dll_ctypes_test.restype = None
dll.dll_ctypes_test(5, ctypes.byref(c_out()))

Llamar al código de Python produce

Traceback (most recent call last):
File "<ipython-input-15-7c8b287888d0>", line 1, in <module>
dll.dll_ctypes_test(5, c_out())
OSError: exception: access violation writing 0x00000062BA400000

Si cambio N_ARRAYSde 50a, digamos, 10. El error desaparece.


Solución del problema

Listado [Python.Docs]: ctypes: una biblioteca de funciones externas para Python.

Debo decir que no pude reproducir el comportamiento (incluso sin corregir los errores a continuación), usando Python "normal" o IPython. Tal vez haya más en la implementación de dll_ctypes_test de lo que parece.

Asuntos actuales:

  • dll_ctypes_test espera un puntero c_out, pero está pasando una instancia simple de c_out. Debe usar ctypes.byref (o ctypes.pointer ). No sé por qué CTypes no se queja por eso.

  • Las definiciones de estructura de C y Python no coinciden. Un ejemplo es arr, que contiene una matriz de elementos en C y una matriz de punteros de elementos ( ctypes.POINTER ) en Python. Este es un comportamiento indefinido, los 2 deben estar sincronizados.

  • Marcó la función de exportación como __stdcall, pero está cargando el.dll con CDLL. Deberías usar WinDLL. Pero como estás en 064 bits (basado en tus rutas), esto no hace mucha diferencia.

  • A continuación se muestra un ejemplo (una versión modificada de su código).

    dll00.h:

    #pragma once
    #if defined(_WIN32)
    # if defined DLL00_EXPORTS
    # define DLL00_EXPORT_API __declspec(dllexport)
    # else
    # define DLL00_EXPORT_API __declspec(dllimport)
    # endif
    #else
    # define DLL00_EXPORT_API

    No hay comentarios:

    Publicar un comentario

    Regla de Firestore para acceder a la generación de subcolección Permisos faltantes o insuficientes

    Tengo problemas con las reglas de Firestore para permitir el acceso a algunos recursos en una subcolección. Tengo algunos requests document...