Уведомления

Группа в Telegram: @pythonsu

#1 Фев. 17, 2009 01:23:24

razr
От:
Зарегистрирован: 2009-02-17
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

Проблема с dll

пишу программу для цифрового 4канального вольтметра (k8047d). использую для этого библиотеку k8047d.dll взятую с сайта производителя (ну и еще вдовесок файлы fasttime32.dll и k8047e.exe, которые нужны для работы k8047d.dll).
в k8047d.dll есть 6 функций:
1) StartDevice()
2) StopDevice()
3) LEDon() - включает лампочку на вольтметре
4) LEDoff() - выключает лампочку на вольтметре
5) SetGain(Channel, Gain) - устанавливает максимальное напряжение (Gain), которое можно подключить к каналу (Channel). Channel может принимать значения 1..4, Gain - 1,2,5,10.
6) ReadData(Buffer) - возвращает массив из 8 элементов. два первых - отвечают за таймер, 4 следующих за напряжение на каналах, а два последних - хз за что (они не нужны)

так вот StartDevice(), StopDevice(), LEDon() и LEDoff() работают.

теперь первый вопрос: при вызове SetGain() вылазит ошибка, хотя вроде правильно всё указываю:

>>> from ctypes import *
>>> lib=cdll.k8047d
>>> lib.StartDevice()
33
>>> lib.SetGain(3,5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Procedure called with not enough arguments (8 bytes missing) or wrong calling convention
и второй: не пойму как получить и работать со значениями ReadData(). вот пример работы с этой функцией на Delphi (взят из описания dll'ки):
var  // global variables  
DataBuffer: ARRAY[0..7] OF Integer;

procedure TForm1.Button1Click(Sender: TObject);
var p:pointer;
i:integer;
s:string;
begin
p:=@DataBuffer; // Address of the data buffer
ReadData(p); // Read the data from K8047
memo1.clear;
s:='';
for i:=0 to 7 do s:=s +inttostr(DataBuffer[i]+chr(9);
memo1.lines.add(s); // Display the data
end;



Офлайн

#2 Фев. 17, 2009 01:45:41

razr
От:
Зарегистрирован: 2009-02-17
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

Проблема с dll

попробовал в SetGain использовать windll вместо cdll:

>>> from ctypes import *
>>> lib=windll.k8047d
>>> lib.StartDevice()
>>> lib.SetGain(1,1)
0
вроде теперь ошибку не выдает. правда не узнаю правильно ли это работает, пока не разберусь с ReadData()



Офлайн

#3 Фев. 17, 2009 03:55:03

pyuser
От:
Зарегистрирован: 2007-05-13
Сообщения: 658
Репутация: +  36  -
Профиль   Отправить e-mail  

Проблема с dll

razr
… правда не узнаю правильно ли это работает, пока не разберусь с ReadData()
если я ничего не путаю, то выглядеть это будет примерно так
from ctypes import *

HEAP_ZERO_MEMORY = 8L

GetProcessHeap = windll.kernel32.GetProcessHeap
HeapAlloc = windll.kernel32.HeapAlloc
HeapFree = windll.kernel32.HeapFree

buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 8 * sizeof(c_int))

ReadData(buffer)

result = (c_int * 8).from_address(buffer)

# result - массив целых, делаем, что надо и освобождаем память
HeapFree(GetProcessHeap(), 0, buffer)



Офлайн

#4 Фев. 17, 2009 15:14:43

razr
От:
Зарегистрирован: 2009-02-17
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

Проблема с dll

pyuser
razr
… правда не узнаю правильно ли это работает, пока не разберусь с ReadData()
если я ничего не путаю, то выглядеть это будет примерно так
from ctypes import *

HEAP_ZERO_MEMORY = 8L

GetProcessHeap = windll.kernel32.GetProcessHeap
HeapAlloc = windll.kernel32.HeapAlloc
HeapFree = windll.kernel32.HeapFree

buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 8 * sizeof(c_int))

ReadData(buffer)

result = (c_int * 8).from_address(buffer)

# result - массив целых, делаем, что надо и освобождаем память
HeapFree(GetProcessHeap(), 0, buffer)
а можно немного пояснений? я ничего не понял)

upd: наконец-то появилось время проверить код - работает!!! огромнейшее спасибо! но от пояснений я б все равно не отказался)



Отредактировано (Фев. 17, 2009 21:12:01)

Офлайн

#5 Фев. 18, 2009 10:17:20

pyuser
От:
Зарегистрирован: 2007-05-13
Сообщения: 658
Репутация: +  36  -
Профиль   Отправить e-mail  

Проблема с dll

razr
а можно немного пояснений? я ничего не понял)

upd: наконец-то появилось время проверить код - работает!!! огромнейшее спасибо! но от пояснений я б все равно не отказался)
может для начала документацию по ctypes почитать :) (http://python.net/crew/theller/ctypes/reference.html, если не знали)

GetProcessHeap = windll.kernel32.GetProcessHeap
HeapAlloc = windll.kernel32.HeapAlloc
HeapFree = windll.kernel32.HeapFree
это функции управления памятью (любой букварь по WinAPI)
buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 8 * sizeof(c_int))
выделяем память под результирующий буфер
ReadData(buffer)
без коментариев :)
result = (c_int * 8).from_address(buffer)
buffer это указатель на блок памяти, сообщаем Python'у, что это массив из восьми целых

код работы с массивом отсутствовал, потому и объяснение отсутствует

HeapFree(GetProcessHeap(), 0, buffer)
освобождаем память (правила хорошего тона)

можно попробовать так (давно с ctypes не работал):
buffer = c_int * 8 # объявляем массив
ReadData(buffer) # или ReadData(byref(buffer)) или ReadData(pointer(buffer)) не помню :(
for i in buffer.values :
print hex(i), # для каждого элемента массива выводим его шеснадцатиричное представление
если это работает, то и не стоит заморачиваться с функциями WinAPI



Офлайн

#6 Фев. 18, 2009 12:31:54

razr
От:
Зарегистрирован: 2009-02-17
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

Проблема с dll

pyuser
может для начала документацию по ctypes почитать :) (http://python.net/crew/theller/ctypes/reference.html, если не знали)
я читал ctypes tutorial и мало что оттуда понял. ctypes reference получше будет.

pyuser
GetProcessHeap = windll.kernel32.GetProcessHeap
HeapAlloc = windll.kernel32.HeapAlloc
HeapFree = windll.kernel32.HeapFree
это функции управления памятью (любой букварь по WinAPI)
buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 8 * sizeof(c_int))
выделяем память под результирующий буфер
вот это мне как раз было непонятно. правда вчера все-таки нагуглил что это за функции. как будет время полистаю какой-нибудь справочник по WinAPI.

pyuser
можно попробовать так (давно с ctypes не работал):
buffer = c_int * 8 # объявляем массив
ReadData(buffer) # или ReadData(byref(buffer)) или ReadData(pointer(buffer)) не помню :(
for i in buffer.values :
print hex(i), # для каждого элемента массива выводим его шеснадцатиричное представление
если это работает, то и не стоит заморачиваться с функциями WinAPI
вечером попробую. без WinAPI все выглядит намного проще)



Офлайн

#7 Фев. 18, 2009 12:40:06

pyuser
От:
Зарегистрирован: 2007-05-13
Сообщения: 658
Репутация: +  36  -
Профиль   Отправить e-mail  

Проблема с dll

razr
вечером попробую. без WinAPI все выглядит намного проще)
:) трудно возразить



Офлайн

#8 Фев. 18, 2009 21:23:46

razr
От:
Зарегистрирован: 2009-02-17
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

Проблема с dll

pyuser
buffer = c_int * 8 # объявляем массив
ReadData(buffer) # или ReadData(byref(buffer)) или ReadData(pointer(buffer)) не помню :(
for i in buffer.values :
print hex(i), # для каждого элемента массива выводим его шеснадцатиричное представление
>>> lib.ReadData(buffer)                                                       
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ctypes.ArgumentError: argument 1: <type 'exceptions.TypeError'>: Don't know how
to convert parameter 1
>>> lib.ReadData(byref(buffer))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: byref() argument must be a ctypes instance, not '_ctypes.ArrayType'
>>> lib.ReadData(pointer(buffer))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: _type_ must have storage info
не работает(( ну значит буду юзать код с WinAPI



Отредактировано (Фев. 18, 2009 21:24:54)

Офлайн

#9 Фев. 19, 2009 02:25:32

pyuser
От:
Зарегистрирован: 2007-05-13
Сообщения: 658
Репутация: +  36  -
Профиль   Отправить e-mail  

Проблема с dll

razr
pyuser
buffer = c_int * 8 # объявляем массив
ReadData(buffer) # или ReadData(byref(buffer)) или ReadData(pointer(buffer)) не помню :(
for i in buffer.values :
print hex(i), # для каждого элемента массива выводим его шеснадцатиричное представление
>>> lib.ReadData(buffer)                                                       
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ctypes.ArgumentError: argument 1: <type 'exceptions.TypeError'>: Don't know how
to convert parameter 1
>>> lib.ReadData(byref(buffer))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: byref() argument must be a ctypes instance, not '_ctypes.ArrayType'
>>> lib.ReadData(pointer(buffer))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: _type_ must have storage info
не работает(( ну значит буду юзать код с WinAPI
я бы еще попробовал:
ReadData(addressof(buffer))



Офлайн

#10 Фев. 20, 2009 20:17:55

razr
От:
Зарегистрирован: 2009-02-17
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

Проблема с dll

pyuser
я бы еще попробовал:
Код:

ReadData(addressof(buffer))
не работает тож



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version