Work with DLL file

Hello,
im trying to work with a DMD from Vialux. All i know is that i have to use the functions from the DLL File. I loaded it and all functions are in the workspace.
Now i want to use at frist one function "AlpDev Alloc". In the Description it says "long AlpDevAlloc (long DeviceNum, long InitFlag, ALP_ID *DeviceIdPtr)". I get three ouputs but i have to give three inputs. First two of them are given as "ALP_DEFAULT" for DeviceNum and InitFlag (4 byte integer value). For "DeviveIdPtr" pointer to a writeable 4-byte integer. Its completly new for me with DLLs, could anyone help with this question what i have to do with "ALP_ID *DevideIdPtr" and is the rest correct?
Thanks a lot!
loadlibrary('alp4395', 'alp.h');
libfunc = libfunctions('alp4395');
% long AlpDevAlloc (long DeviceNum, long InitFlag, ALP_ID *DeviceIdPtr) in documentation
[res1, res2, res3] = calllib('alp4395',libfunc{1,1},'ALP_Default', 'ALP_Default',?);

5 个评论

you will need to create a pointer before you can call the function
ptr = libpointer(DataType); % e.g. DataType = 'int32'
DeviceNum = 1;
InitFlag = 1;
[res1, res2, res3] = calllib('alp4395','AlpDevAlloc',DeviceNum,InitFlag,ptr);
Hello Mohammad,
thanks for your Answer! I tried your suggestion but it doenst work (No method with matching signature.). Should'nt i write for DeviceNum and InitFlag 'ALP_DEFAULT'? The arguments are (long, long, ulongPtr) and the return type [long, ulongPtr], Just two outputs and instead of int32 -> uint32, right?
i tried this
ALP_ID = libpointer('uint32'); % e.g. DataType = 'int32'
DeviceNum = 'ALP_DEFAULT';
InitFlag = 'ALP_DEFAULT';
[res1, res2] = calllib('alp4395','AlpDevAlloc',DeviceNum,InitFlag,ALP_ID);
and the following error is "Parameter must be scalar."
Mohammad Sami
Mohammad Sami 2020-1-28
编辑:Mohammad Sami 2020-1-28
Is ALP_DEFAULT a constant defined in the dll ? I think you will need to pass in the actual numeric value of the constant as the signature asks for long. ulongPtr would be uint32 pointer.
Also do note the pointer is initialised to a null value.
I want to show the information i have.
From the Description ( AlpDevAlloc Function):
From the h. - File:
Should i set DeviceNum and InitFlag to 0 or is this value i get as return? I thought i have to write it as a string in the calllib function.
For ALP_Default = 0:
ID = 0;
ALP_ID = libpointer('uint32',ID); % e.g. DataType = 'int32'
DeviceNum = 0;
InitFlag = 0;
[res1, res2] = calllib('alp4395','AlpDevAlloc',DeviceNum,InitFlag,ALP_ID);
This gives me an error in Calllib "Array must be numeric or logical or a pointer to one.".
Something happend i tried this:
ID = 0;
ALP_ID = libpointer; % e.g. DataType = 'int32'
DeviceNum = 0;
InitFlag = 0;
[res1, res2] = calllib('alp4395','AlpDevAlloc',DeviceNum,InitFlag,ALP_ID);
I get no error and in the workspace for res1 = 1001 and res2 = [ ]. At the moment the device is not connected. Maybe if its connected res2 should show me ALP_ID.
I'm in the laboratory now and i used this:
deviceid = uint32(0);
ALP_ID = libpointer('uint32Ptr', deviceid);
DeviceNum = uint32(0);
InitFlag = uint32(0);
[x1, x2] = calllib('alp4395','AlpDevAlloc',DeviceNum,InitFlag,ALP_ID);
My two ouputs [long, longPtr] are x1 = 1001 and x2 = 0. x1 should be alp_returnvalue and x2 the ALP_ID. But 0 seems not like an ID.
Can you check in the dll documentation what a return value of 1001 mean?

请先登录,再进行评论。

回答(2 个)

Your dll function takes 3 inputs, the first two are scalar numeric indeed. The snippet of documentation you show is not very clear but indeed it looks like you want 0 for the default.
The 3rd input is a pointer to some memory where the function will write something.From your header file snippet it looks like it is indeed a 4-bit unsigned integer (assuming that the dll defines long as a 32-bit integer, which is fairly standard but not guaranteed).
The function only has one output, which is probably an error code or success. I'm unclear why you say you get 3 outputs.
In theory,
deviceptr = libpointer('uint32'); %No need to assign a value, it's overwritten by AlpDevAlloc
res = calllib('alp4395', 'AlpDevAlloc', 0, 0, deviceptr);
ALP_ID = deviceptr.Value;
should work according to the information you've provided. However, do check the value of res against the dll documentation as it may indicate an error of some kind.
If you get a matlab error with the above, then we've not properly understood the signature.
Note that when you did:
ALP_ID = libpointer;
res1 = calllib('alp4395','AlpDevAlloc',DeviceNum,InitFlag,ALP_ID);
you passed a NULL pointer to the library. Two things can happen in this case: the library tries to write to the NULL address and crashes, or the dll checks that the pointer is not NULL and returns an error. Since it didn't crash, it must have returned an error code which I assumes is that 1001 value.
Peer Blumido
Peer Blumido 2020-1-28
编辑:Peer Blumido 2020-1-28
Hello Guillaume,
thanks for your answer! Thats what ive got about the Function AlpDevAlloc:
I know it wasnt correct that i receive 3 outputs. Im so sorry if i did many dumb mistakes but this is completly new for me. Never worked with DLLs before.
I would suggest this, because it worked without any Error.
loadlibrary('alp4395.dll', 'alp.h');
libfunc = libfunctions('alp4395');
deviceid = uint32(0);
ALP_ID = libpointer('uint32Ptr', deviceid);
DeviceNum = int32(0);
InitFlag = int32(0);
[alp_returnvalue, ALP_ID] = calllib('alp4395','AlpDevAlloc',DeviceNum,InitFlag,ALP_ID);
i hope this can help more find the issue.
i dont know what happend but i wrote at the end
unloadlibrary('alp4395')
and matlab crashed. After removing this and new run i had this in workspace:
5.png
After a second run it turned to the values in workspace above.

8 个评论

"matlab crashed": do you really mean crash (you have to restart matlab) or error? If matlab did crash, that's a problem with the dll itself, not much you can do about that. Possibly, the dll doesn't behave well if it still holds resources when it is unloaded. Only the dll authors can fix this.
So, yes if you get 1001 that means that the function call worked but you either passed some invalid values or the device can't be connected to. It looks like it worked on your second try and you connected to a device with ID 353.
Most likely, if you're connected and you attempt another connection, you'll get error 1001.
Make sure that you call AlpDevFree if you succesfully connected. That may help in preventing crashes.
Yes, you would need to deallocate any resources, before unloading the dll. I have experienced such crashes before.
Based on what worked. device id is pointer to uint32 = unsigned long, while the DeviceNum and InitFlag are int32 = long.
So the error in my earlier comment was not to explicitly initialise DeviceNum and InitFlag as int32 class. I had thought matlab will translate this automatically, based on the function signature.
If you need to use this interface often, I would recommend that you make your own Matlab Wrapper class around your dll. That way you can track if the library is loaded and all the resources that you have kept open. You will need to write a custom delete function to free up the open resources and unload the library.
Like Mohammad, I'm a bit surprised that you have to explicitly tell cast the values to their respective C type. Matlab is supposed to do that for you.
Mohammad suggestion of wrapping the dll into a class is a very good one. It would go something like this:
classdef ALPWrapper < handle
properties %store here all resources that must be released before unloading
allocatedALP; %array to store all allocated devices. They must be deallocated prior to unloading
end
properties (Constant, Access = Private)
libname = 'alp4395'
end
methods
function this = ALPWrapper %constructor
%load the library
loadlibrary('alp4395.dll', 'alp.h');
%other initialisation tasks
end
function delete(this) %destructor
for dev = 1:numel(allocatedALP)
this.FreeDevice(allocatedALP(dev));
end
%after freeing all resources unload the library
unloadlibrary('alp4395');
end
function AllocateDevice(this, DeviceNumber, InitFlag)
deviceid = 0; %gets overwritten by AlpDevAlloc
devptr = libpointer('uint32Ptr', 0);
errcode = calllib(this.libname, 'AlpDevAlloc', DeviceNumber, InitFlag, devptr);
if errcode ~= 0
error('Failed to allocated device, error code is: %d', errcode);
end
this.allocatedALP = [this.allocatedALP, devptr.Value];
end
function FreeDevice(this, DeviceId)
[found, where] = ismember(DeviceId, this.allocatedALP);
assert(found, 'Device has not been allocated');
errcode = calllib(this.libname, 'AlpDevFree', DeviceId); %I'm making assumption about the signature of this function
if errcode ~= 0
warning('Deallocation may not have been successful, error code is: %d', errcode);
end
this.allocatedALP(where) = [];
end
end
end
To unload the library, you just have to clear the class object, e.g.:
alplib = ALPWrapper; %this loads the library and perform any required initialisation
alpid = alplib.AllocateDevice(0, 0); %use defaults
%...do something
clear('alplib'); %automatically deallocate device and unload the library
Thank you so much both of you!
Yes Matlab crashed and i had to restart matlab. The Wrapper class is a good idea, i will go through it step by step to understand how its working but this will take a bit time :)
At the moment it seems to work. The DMD light turns off for milliseconds (Allocating) and then after free the device its turning on. No Errors, no crash.
clearvars
loadlibrary('alp4395.dll', 'alp.h');
libfunc = libfunctions('alp4395');
deviceid = uint32(0);
ALP_ID = libpointer('uint32Ptr', deviceid);
DeviceNum = int32(0);
InitFlag = int32(0);
[alp_returnvalue, ALP_ID] = calllib('alp4395','AlpDevAlloc',DeviceNum,InitFlag,ALP_ID);
calllib('alp4395','AlpDevFree',ALP_ID);
%clear('alp3495');
unloadlibrary('alp4395');
After run many times the ALP_ID is changing from 298 to 7, 48, 69, 93, 118 and so on. Do you think this is on purpose that the dll function generate random IDs?
Before i continue going through all functions in the first example i gave the function "AlpDevAlloc" inputs of Devicenum and InitFlag = 0 as ALP_Default. The next function i want to try is "AlpDevControl".
6.png
DeviceId is the value i got in the workspace so i just take this. They say all functions will return a 4-byte integer.
7.png
% First Try
calllib('alp4395','AlpDevControl',ALP_ID,ControlType,ControlValue); %This might not work
% Second Try, no Error and 0 as value in workspace, doesnt make sense
ControlType = int32(0);
ControlValue = int32(0);
calllib('alp4395','AlpDevControl',ALP_ID,ControlType,ControlValue);
% Third Try, but should be my Ouput which i can controll with the h.file
ControlType = ?; % Value from Header File?
ControlValue = ?; % Value from Header File?
calllib('alp4395','AlpDevControl',ALP_ID,ControlType,ControlValue);
Its not obvious for me how to receive these return values.
8.png
Regarding return value, it sounds like it's always going to be an error code, so you'll be calling all the functions with:
errcode = calllib(['alp4395', 'funname', arg1, arg2, ..);
and if you don't get 0 as errcode, something is not right. You posted the meaning of the error codes earlier. E.g if errcode is 1005, this is ALP_PARM_INVALID meaning you passed an invalid value to the function.
No idea why the device ID is changing. It's totally up to the authors of the dll how this work. You need to ask them.
With regards to AlpDevControl, well you need to decide what operation you want to perform (1st argument) and the corresponding value you want to set. E.g if you want to set the DMD type to 1080 .65'' type A, the control type is 2021 (ALP_DEV_DMDTYPE) and the control value is 10 (ALP_DMDTYPE_1080P_065A), so:
errcode = calllib('ap4395', 'AlpDevControl', ALP_ID, 1080, 10);
To disable timeout:
errcode = calllib('ap4395', 'AlpDevControl', ALP_ID, 2014, 1); %ALP_TRIGGER_TIME_OUT, ALP_TIME_OUT_DISABLE
etc.
Hello!
yes i did this. The values need to set as int32().
%% AlpDevControl
ControlType = int32(2021);
ControlValue = int32(10);
AlpDevStatus = calllib('alp4395', 'AlpDevControl', ALP_ID, ControlType, ControlValue);
I tried some functions to get more experience and to find out how they work or what i have to write for parameters etc.
%% AlpDevInquire
UserVar = int32(0);
UserVarPtr = libpointer('int32Ptr',UserVar);
InquireType1 = int32(2000);
InquireType2 = int32(2057);
InquireType3 = int32(2058);
InquireType4 = int32(2016);
InquireType5 = int32(2050);
InquireType6 = int32(2052);
[~, ALP_SerialNum] = calllib('alp4395','AlpDevInquire',ALP_ID,InquireType1,UserVarPtr); % DMD Serial Nummer
[~, Alp_Height] = calllib('alp4395','AlpDevInquire',ALP_ID,InquireType2,UserVarPtr); % DMD Höhe
[~, ALP_Width] = calllib('alp4395','AlpDevInquire',ALP_ID,InquireType3,UserVarPtr); % DMD Breite
[~, ALP_USB] = calllib('alp4395','AlpDevInquire',ALP_ID,InquireType4,UserVarPtr); % USB Connection
[~, ALP_Temp] = calllib('alp4395','AlpDevInquire',ALP_ID,InquireType5,UserVarPtr); % DLPC FPGA Temp
ALP_Temp = ALP_Temp/256;
[~, ALP_Temp_PCB] = calllib('alp4395','AlpDevInquire',ALP_ID,InquireType6,UserVarPtr); % DLPC FPGA Temp
ALP_Temp_PCB = ALP_Temp_PCB/256;
And these are my results :)
9.png
Looks like you have manage to get it to work. You can add these as functions in your wrapper class.
Also I would recommend that your class manage all the pointers internally. If any of the c functions return pointers those may need to be freed once you don't need them or when you are deleting this object.
What I did was to create a private property to store pointers in a cell array. Once the pointer is cleared in C (your dll my have a clear or free function), just set it to libpointer (null).
If a function in c returns a pointer, its stored in the cell array, and i return the cell array index rather then the pointer.
% release pointers
if(~obj.pointers{i}.isNull)
calllib('lib...','release....free...',obj.pointers{i});
obj.pointers{i} = libpointer; % set to null
end

请先登录,再进行评论。

类别

帮助中心File Exchange 中查找有关 Performance and Memory 的更多信息

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by