список экспортируемых функций из dll с ctypes - PullRequest
33 голосов
/ 23 мая 2010

Есть ли способ узнать, какие функции экспортируются из dll через библиотеку внешних функций python ctypes?

А по возможности узнать подробности об экспортируемых функциях через c types.

Если да, может ли кто-нибудь предоставить фрагмент кода?

Ответы [ 7 ]

15 голосов
/ 23 мая 2010

Я не думаю, что ctypes предлагает эту функцию.На Windows с Visual Studio:

DUMPBIN -EXPORTS XXX.DLL

Или для Mingw на Windows:

objdump -p XXX.dll
10 голосов
/ 09 апреля 2014

Если вы работаете в Linux, есть удобная утилита nm для отображения содержимого общей библиотеки (в Linux всегда есть удобная утилита, особенно для C).Вот вопрос об этом.

Вы используете его с флагом -D: nm -D ./libMyLib.so

7 голосов
/ 23 мая 2010

В общем, это невозможно, потому что, как правило, динамически загружаемые библиотеки не несут нужную вам метаинформацию.В некоторых особых случаях может быть возможно получить эту информацию системно-специфическими способами, но ctypes сама не получает эту информацию.Вы можете записать такую ​​информацию с помощью ctypes (см., Например, атрибуты restype и argtypes указателей функций), но только после того, как вы получили ее различными способами.

5 голосов
/ 03 ноября 2014

@ В ответе Марка используются инструменты Visual Studio.

В Windows вы также можете использовать Dependency Walker для получения имен функций экспорта dll.

Иногда имена искажаются и не могут использоваться в качестве допустимого имени функции python.

Вы можете использовать getattr, чтобы получить указатель на искаженные функции, например:

mylib = ctypes.cdll('mylib.dll')
my_func = getattr(mylib, '_my_func@0')

my_func()
1 голос
/ 19 января 2017

Если у вас также есть источник для указанной библиотеки, и вы ищете полностью автоматизированный полностью-Python способ, вы можете использовать pycparser

для файла: prog.c

typedef short int ret_t;
typedef short int param_t;

ret_t add(param_t a, param_t b) {
    return (ret_t)(a + b);
}

ret_t passthrough(ret_t (* func)(param_t a, param_t b), param_t a, param_t b) {
    // parameter intentionally altered.
    // if this isn't done, compiler will deem entire function redundant
    return func(a, b + 1);
}

компиляция с gcc

gcc -I. -E ./prog.c > prog-preproc.c

дает нам предварительно обработанный файл c: prog-preproc.c затем в python:

import pycparser
parser = pycparser.c_parser.CParser()

with open('prog-preproc.c', 'r') as fh:
    ast = parser.parse(fh.read())

class FunctionVisitor(pycparser.c_ast.NodeVisitor):
    def visit_FuncDef(self, node):
        print("found function: %s" % node.decl.name)
        #node.show()

FunctionVisitor().visit(ast)

выходы

found function: add
found function: passthrough

Чтобы копать дальше, вы также можете получить параметры и возвращаемые типы. Раскомментируйте node.show() для получения дополнительной информации из дерева абстрактного синтаксиса (AST)

Я скоро выпустлю библиотеку (постараюсь не забыть вернуться и сбросить ссылку)

0 голосов
/ 08 марта 2018

ДА!есть очень умный нативный способ сделать это.

допустим, вы используете Python ctypes.поместите что-то вроде этого в коде C:

1) в коде C:

#define PYEXPORT extern "C" __declspec(dllexport)

теперь поместите PYEXPORT над функцией, которую вы хотите экспортировать:

PYEXPORT
int myfunc(params){

2) После компиляции вернитесь в Python и откройте ваш файл .c и проанализируйте его следующим образом:

source1_ = open(cfile_name + '.c')
source1 = source1_.read()
source1_.close()
fn = source1.split('PYEXPORT')[-1].split('(')[0].split(' ')[1]

ввод оболочки: fn

вывод оболочки: 'myfunc'

3) Теперь умная часть: определите новую функцию в строке:

a1 = """
global get_c_fn
def get_c_fn(dll):
     func = dll."""
a2 = """
return func"""
a3 = a1 + fn + a2

print(a3)
global get_c_fn
def get_c_fn(dll):
    func = dll.myfunc
    return func

СЕЙЧАС выполните exec (a3), и она превратит эту строку в функцию, которую вы можете использовать.

4) выполните обычные действия:

mydll = ctypes.CDLL(cfile_name + '.dll')
c_fn = get_cuda_fn(mydll)
c_fn.argtypes =  func_params (an array of C-converted inputs you need)
c_fn( *[params] )

, и там у вас есть оболочка Python для сценария C без необходимости изменять десять разных вещей каждый раз, когда что-то меняется.

0 голосов
/ 03 декабря 2014

Внутренне ctypes использует функции, предоставляемые динамически подключаемой библиотекой (dlopen / dlsym в unix, LoadLibrary / GetProcAddress в windows) для загрузки библиотеки и поиска адреса функции, указанного в имени функции;а затем использовать библиотеку cffi для динамической передачи параметра.

Проблема заключается в том, что библиотека динамической компоновки, от которой зависит ctypes, не включает функцию для вывода списка символов из общей библиотеки, поэтому вы не можете перечислить символы по типам ctypes..

Чтобы сделать это, вы должны использовать специальные инструменты для вывода файла elf (readelf в unix) и файла pe для dll (dumpbin в windows).

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