Calling DLL function

155 views
Skip to first unread message

Jérémy Béjanin

unread,
Oct 5, 2016, 12:51:26 PM10/5/16
to julia-users
Hello,

I am trying to call a DLL function to allocate a page aligned array from julia. Here is a C++ example using that function. Note that the DLL function is wrapped into this uvAPI api, but is otherwise the same except for the name. The DLL function is called x_MemAlloc, while the API function is called X_MemAlloc. The function should return 0 on success, or 1 on failure.

#define DIG_BLOCK_SIZE 1024 * 1024

uvAPI *uv = new uvAPI;
unsigned char * sysMem = NULL;
error = uv->X_MemAlloc((void**)&sysMem, DIG_BLOCK_SIZE);
if (error)
{
 std::cout << "failed to allocate block buffer" << std::endl;
 return  -1;
}

Here is my julia code:

DIG_BLOCK_SIZE = 1024 * 1024
block
= Array{Cuchar}(DIG_BLOCK_SIZE)
if ccall((:x_MemAlloc,AcqSynth),Cint,(Ptr{Ptr{Void}},Csize_t),pointer(block),DIG_BLOCK_SIZE)==1
    error
("Failed to allocate block buffer!")
end

However, the function returns 1 whether I use Ptr{Void} and block, or Ptr{Ptr{Void}} and pointer(block). Is this the proper translation?

I am trying the acquire data with a PCIe digitizer and currently reading out the data into the buffer does not work. I am wondering if this is because the buffer is not allocated properly.

Note that other DLL functions I've tried work properly.

Thanks,
Jeremy

Yichao Yu

unread,
Oct 5, 2016, 1:05:27 PM10/5/16
to Julia Users

On Oct 5, 2016 12:51 PM, "Jérémy Béjanin" <jeremy....@gmail.com> wrote:
>
> Hello,
>
> I am trying to call a DLL function to allocate a page aligned array from julia. Here is a C++ example using that function. Note that the DLL function is wrapped into this uvAPI api, but is otherwise the same except for the name. The DLL function is called x_MemAlloc, while the API function is called X_MemAlloc. The function should return 0 on success, or 1 on failure.
>
> #define DIG_BLOCK_SIZE 1024 * 1024
>
> uvAPI *uv = new uvAPI;
> unsigned char * sysMem = NULL;
> error = uv->X_MemAlloc((void**)&sysMem, DIG_BLOCK_SIZE);
> if (error)
> {
>  std::cout << "failed to allocate block buffer" << std::endl;
>  return  -1;
> }
>
> Here is my julia code:
>
> DIG_BLOCK_SIZE = 1024 * 1024

out = Ref{Ptr{Cuchar}}()
if ccall((:x_MemAlloc,AcqSynth),Cint,(Ptr{Ptr{Cuchar}},Csize_t),out,DIG_BLOCK_SIZE)==1


>     error("Failed to allocate block buffer!")
> end

block = pointer_to_array(out[], DIG_BLOCK_SIZE)

# add finalizer

Jérémy Béjanin

unread,
Oct 6, 2016, 5:40:01 PM10/6/16
to julia-users
Thanks! this works perfectly.

The pointer_to_array() function seems to be deprecated, however, do you know how to use the suggested replacement, unsafe_wrap()?

And if it's not too much to ask, I am wondering how I can do the conversion from this UInt8 buffer more efficiently. This is what I am currently doing, where blocks is the buffer:

# We now have all the blocks in the blocks array, we need to extract the
# 12-bit samples from that array. The data in the blocks is organized in 4
# bytes / 32-bit words, and each word contains two 12-bit samples.
# Calculate the number of 32-bit words in the blocks array
numwords = div(numblocks*DIG_BLOCK_SIZE,4)
# Initialize array to store the samples
data = Array{Int32}(2*numwords)
for n=1:numwords
    # Convert next four bytes to 32-bit string
    s = reverse(bits(blocks[(n-1)*4+1]))*reverse(bits(blocks[(n-1)*4+2]))*reverse(bits(blocks[(n-1)*4+3]))*reverse(bits(blocks[(n-1)*4+4]))
    # Parse the first 12 bits as the first sample and the 12 bits 4 bits later as the second sample
    data[(n-1)*2+1] = parse(Int,reverse(s[1:12]),2)
    data[(n-1)*2+2] = parse(Int,reverse(s[17:28]),2)
end

This is pretty slow, I assume due to the translation between numbers and strings. Is there a better way to do this?

Thanks,
Jeremy

Yichao Yu

unread,
Oct 6, 2016, 8:15:41 PM10/6/16
to Julia Users
On Thu, Oct 6, 2016 at 5:40 PM, Jérémy Béjanin <jeremy....@gmail.com> wrote:
> Thanks! this works perfectly.
>
> The pointer_to_array() function seems to be deprecated, however, do you know
> how to use the suggested replacement, unsafe_wrap()?

Yes.

>
> And if it's not too much to ask, I am wondering how I can do the conversion
> from this UInt8 buffer more efficiently. This is what I am currently doing,
> where blocks is the buffer:
>
> # We now have all the blocks in the blocks array, we need to extract the
> # 12-bit samples from that array. The data in the blocks is organized in 4
> # bytes / 32-bit words, and each word contains two 12-bit samples.
> # Calculate the number of 32-bit words in the blocks array
> numwords = div(numblocks*DIG_BLOCK_SIZE,4)
> # Initialize array to store the samples
> data = Array{Int32}(2*numwords)
> for n=1:numwords
> # Convert next four bytes to 32-bit string
> s =
> reverse(bits(blocks[(n-1)*4+1]))*reverse(bits(blocks[(n-1)*4+2]))*reverse(bits(blocks[(n-1)*4+3]))*reverse(bits(blocks[(n-1)*4+4]))
> # Parse the first 12 bits as the first sample and the 12 bits 4 bits
> later as the second sample
> data[(n-1)*2+1] = parse(Int,reverse(s[1:12]),2)
> data[(n-1)*2+2] = parse(Int,reverse(s[17:28]),2)
> end
>
> This is pretty slow, I assume due to the translation between numbers and
> strings. Is there a better way to do this?

I don't know what exactly the format is but you should not go though
string and you should be able to do what you want with simple
interger/bits operations.

>
> Thanks,
> Jeremy
>

Jérémy Béjanin

unread,
Oct 7, 2016, 12:10:44 PM10/7/16
to julia-users
The format is fairly complicated, but I need to take 4 bytes from that buffer and extract two 12-bit numbers from that 32-bit string (along with some reversing operations, as you can see in the function). I cannot seem to find bit operations that address/concatenate individual bits without going through a string format and parsing. Would you have any guidance as to where in the manual I should look?

Yichao Yu

unread,
Oct 7, 2016, 12:27:36 PM10/7/16
to Julia Users
On Fri, Oct 7, 2016 at 12:10 PM, Jérémy Béjanin
<jeremy....@gmail.com> wrote:
> The format is fairly complicated, but I need to take 4 bytes from that
> buffer and extract two 12-bit numbers from that 32-bit string (along with
> some reversing operations, as you can see in the function). I cannot seem to
> find bit operations that address/concatenate individual bits without going
> through a string format and parsing. Would you have any guidance as to where
> in the manual I should look?

I didn't follow that way too complicated string handling but sth on the line of
a & 0xfff
and
(a >> 16) & 0xfff
should do it.
You need to adjust to the actual bits location of course.

If you have never done anything with bits before, this might be useful
in general. https://en.wikipedia.org/wiki/Bitwise_operation
Reply all
Reply to author
Forward
0 new messages