簡體   English   中英

使用 Python 調用 DLL 函數時出現 ctypes.ArgumentError

[英]ctypes.ArgumentError when calling DLL functions with Python

我正在使用 ctypes 根據描述 DLL 函數的參數和返回的描述文件來調用 DLL 文件中的函數。 這是此 DLL 中的一個函數,稱為 InitNetwork。 下面是它的描述:

Function:BOOL InitNetwork(char  LocalIP[],char  ServerIP[],int  LocalDeviceID);
Arguments:LocalIP
           ServerIP
           LocalDeviceID
Return:Success:TRUE;
        Faile:FALSE;

我在 Python 中所做的事情是這樣的:

from ctypes import *
import os

#Load Dll:
cppdll = CDLL("C:\\VS_projects\\MusicServer_Flask\\NetServerInterface.dll")

#Get the function:
initnetwork = getattr(cppdll, "?InitNetwork@@YAHQAD0H@Z")  # The function can be successfully accessed.

#specify arguments' types:
initnetwork.argtypes = [c_char_p,c_char_p,c_int]

在此之后,我嘗試:

initnetwork("192.168.1.103", "192.168.1.103", 1111)

得到一個錯誤:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type

如果我試試這個:

initnetwork(LocalIP = "192.168.1.103", ServerIP = "192.168.1.103", LocalDeviceID = 1111)

我會得到:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: this function takes at least 3 arguments (0 given)

為什么會出現這些錯誤? 如何成功調用此函數? 任何建議表示贊賞。 感謝您的關注!

ctypes官方文檔: [Python 3.5]:ctypes - Python 的外部函數庫

創建了一個虛擬.dll來模仿您的行為。

dll.c

#include <stdio.h>
#include <Windows.h>


__declspec(dllexport) BOOL InitNetwork(char LocalIP[], char ServerIP[], int LocalDeviceID) {
    printf("From C:\n\tLocalIP: [%s]\n\tServerIP: [%s]\n\tLocalDeviceID: %d\n", LocalIP, ServerIP, LocalDeviceID);
    return TRUE;
}

檢查[SO]:如何編譯用 C 編寫的 64 位 dll? (@CristiFati 的回答)詳細了解如何構建它(采取完全相同的步驟,在這種情況下的命令是: cl /nologo /LD /DWIN64 /DWIN32 /Tp dll.c /link /OUT:NetServerInterface.dll )。

(主要)問題是在Python3中, char*不再映射到string ,而是映射到bytes對象。

代碼.py

import sys
import ctypes
from ctypes import wintypes


FILE_NAME = "NetServerInterface.dll"
FUNC_NAME = "?InitNetwork@@YAHQEAD0H@Z"  # Name different than yours: if func was declared as `extern "C"`, the "normal" name would be required


def main():
    net_server_interface_dll = ctypes.CDLL(FILE_NAME)
    init_network = getattr(net_server_interface_dll, FUNC_NAME)

    init_network.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_int]
    init_network.restype = wintypes.BOOL

    init_network(b"192.168.1.103", b"192.168.1.103", 1111)


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

輸出

 (py35x64_test) e:\Work\Dev\StackOverflow\q050325050>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" code.py Python 3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32 From C: LocalIP: [192.168.1.103] ServerIP: [192.168.1.103] LocalDeviceID: 1111

我認為問題出在你的 C++ 接口上。 我想如果你把它改成 Function:BOOL InitNetwork(char * LocalIP,char * ServerIP,int LocalDeviceID);

您的第一次調用(沒有關鍵字)應該可以工作,但我認為您可能需要刪除最后一個參數周圍的引號(畢竟它是一個 int )。

Python 3.7 也面臨同樣的問題,默認為 UTF-8。 所以用utf轉字節

library_handler = ctypes.windll.LoadLibrary('my_api.dll')

dll_fu = library_handler.DllFunc
dll_fu.argtypes = [ctypes.c_char_p,
                     ctypes.c_char_p,
                     ctypes.c_char_p,
                     ctypes.c_char_p]

result_code = dll_fu(param1.encode('utf-8'),
                    param2.encode('utf-8'),
                    param3.encode('utf-8'),
                    param4.encode('utf-8'))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM