Обтекание функций DLL с использованием ctypes - PullRequest
0 голосов
/ 27 апреля 2018

Я сейчас обертываю некоторые функции в C ++ dll, чей оригинальный .h файл .cpp недоступен. После изучения учебника по ctypes у меня остались некоторые вопросы. Позвольте мне показать вам пример: Это из файла описания функций dll, просто сообщая имена функций, эффекты и параметры:

#initialize network:
BOOL InitNetwork(char LocalIP[],char ServerIP[],int LocalDeviceID)

#judging if the server is online after network initialization:
BOOL GetOnlineStatus()

#get song name:
char* GetMusicSongName(int DirIndex,int SongIndex)

#making the device playing music:
int PlayServerMusic(int DirIndex,int MusicIndex,int DeviceCout,PUINT lpDeviceID,int UseListIndex,int UserMusicIndex,UINT TaskCode)

Чтобы обернуть эти функции в Python, я попытаюсь сделать следующее:

import ctypes
import os

#load dll
cppdll = ctypes.WinDLL("C:\\VS_projects\\MusicWebService\\MusicWebService\\NetServerInterface.dll")

#wrap dll functions:

#initialize network:
def InitNetwork(LocalIP, ServerIP, LocalDeviceID):
    return cppdll.InitNetwork(LocalIP, ServerIP, LocalDeviceID)
InitNetwork.argtypes = [c_char, c_char, c_int]

#judging if the server is online after network initialization:
def GetOnlineStatus():
    return cppdll.GetOnlineStatus()

#get song name:
def GetMusicSongName(DirIndex, SongIndex):
    return cppdll.GetMusicSongName(DirIndex, SongIndex)
GetMusicSongName.argtypes = [c_int, c_int]

#making the device playing music:
def PlayServerMusic(DirIndex, MusicIndex, DeviceCout, lpDeviceID, UseListIndex, UserMusicIndex, TaskCode):
    return cppdll.PlayServerMusic(DirIndex, MusicIndex, DeviceCout, lpDeviceID, UseListIndex, UserMusicIndex, TaskCode)

Когда я набираю и определяю первую функцию (после импорта пакетов и загрузки библиотеки DLL) в окне взаимодействия Python VS2015, выдается сообщение об ошибке:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'c_char' is not defined

Нужно ли указывать тип входных параметров? Если так, как это сделать? Я не могу распознать тип некоторых параметров в четвертой функции, таких как PUINT lpDeviceID и UINT TaskCode. Как их указать? Кроме того, мне нужно указать тип возвращаемого значения функции? Если да, то как их указать? Может ли кто-нибудь дать мне правильный код переноса из приведенных выше примеров? Спасибо за внимание!

Ответы [ 2 ]

0 голосов
/ 27 апреля 2018

Вот полный набор определений, которые должны работать. Обратите внимание, как передать выходной параметр, создав экземпляр типа и передав его по ссылке. Многие общие типы Windows также определены в ctypes.wintypes.

Обратите внимание, что для InitNetwork первыми типами параметров являются char* в C, поэтому вам нужно c_char_p, а не c_char, и вы можете напрямую передавать байтовые строки Python, поскольку код C не записывает указатели. ctypes.create_string_buffer() может использоваться для генерации записываемого массива char при необходимости.

from ctypes import *
from ctypes import wintypes as w

dll = WinDLL('path/to/dll')

# BOOL InitNetwork(char LocalIP[],char ServerIP[],int LocalDeviceID)
dll.InitNetwork.argtypes = c_char_p,c_char_p,c_int
dll.InitNetwork.restype = w.BOOL

# BOOL GetOnlineStatus()
dll.GetOnlineStatus.argtypes = None
dll.GetOnlineStatus.restype = w.BOOL

# char* GetMusicSongName(int DirIndex,int SongIndex)
dll.GetMusicSongName.argtypes = c_int,c_int
dll.GetMusicSongName.restype = c_char_p

# int PlayServerMusic(int DirIndex,int MusicIndex,int DeviceCout,PUINT lpDeviceID,int UseListIndex,int UserMusicIndex,UINT TaskCode)
dll.PlayServerMusic.argtypes = c_int,c_int,w.PUINT,c_int,c_int,w.UINT
dll.PlayServerMusic.restype = c_int

dll.InitNetwork(b'1.1.1.1',b'2.2.2.2',7)
status = dll.GetOnlineStatus()
song = dll.GetMusicSongName(1,2)
DeviceCout = w.UINT()
result = dll.PlayServerMusic(1,2,3,byref(DeviceCout),4,5,6)
0 голосов
/ 27 апреля 2018

Ваша проблема в том, что у вас не совсем правильные пространства имен. Его

cppdll.InitNetwork.argtypes = [ctypes.c_char, ctypes.c_char, ctypes.c_int]

Вы можете импортировать необходимые данные ctypes непосредственно в модуль. А поскольку ctypes создает оболочки функций для вас, вам на самом деле не нужен собственный def, чтобы делать то же самое. Вы можете вызывать их с помощью cppdll.Whatever, но если вам нравится иметь функции на уровне пространства имен, вы можете просто создать для них переменные.

from ctypes import WinDLL, c_char, c_int
import os

#load dll
cppdll = ctypes.WinDLL("C:\\VS_projects\\MusicWebService\\MusicWebService\\NetServerInterface.dll")

#initialize network:
InitNetwork = cppdll.InitNetwork
InitNetwork.argtypes = [c_char, c_char, c_int]

#judging if the server is online after network initialization:
GetOnlineStatus = cppdll.GetOnlineStatus

#get song name:
GetMusicSongName = cppdll.GetMusicSongName
GetMusicSongName.argtypes = [c_int, c_int]

#making the device playing music:
PlayServerMusic = cppdll.PlayServerMusic
PlayServerMusic = ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...