Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a DLL exported from D

Tags:

python

dll

d

I've created a simple encryption program in D, and I had the idea to make a DLL from it and try to import it to, for example, Python.

I've could simply call my main function, becouse it dosn't need any params. But when I get to my encrytion method, it uses dynamic-lenght ubyte[] arrays, but as far as I know, they don't exist in other C/C++ based langs.

For example, there's the first line of one of my funcs:
ubyte[] encode(ubyte[] data, ubyte[] key){

But I can't use an array without fixed lenght in other languages! How can I import that function, for example, in Python?

EDIT:

I know that I can create a wrapper that takes a pointer and the lenght of the array, but isn't there a more elegant solution?
(Where I don't need to use D to use a lib written in D)

like image 440
Sasszem Avatar asked Sep 21 '16 16:09

Sasszem


1 Answers

Well tbh. there's no real elegant way other than wrapping a pointer with a length or wrapping to C arrays and then to D.

However you can make a somewhat elegant purpose with the first way using a struct that has a pointer, a length and a property that converts it to a D array.

Then the function you export takes your struct, all that function should do is call an internal function that takes an actual D array and you'd simply pass the array to it and the conversion would happen at that moment through alias this and the conversion property.

An example usage is here: module main;

import core.stdc.stdlib : malloc;

import std.stdio;

struct DArray(T) {
    T* data;
    size_t length;
    /// This field can be removed, only used for testing purpose
    size_t offset;

    @property T[] array() {
        T[] arr;

        foreach(i; 0 .. length) {
            arr ~= data[i];
        }

        return arr;
    }

    alias array this;

    /// This function can be removed, only used for testing purpose
    void init(size_t size) {
        data = cast(T*)malloc(size * T.sizeof);
        length = size;
    }

    /// This function can be removed, only used for testing purpose
    void append(T value) {
        data[offset] = value;

        offset++;
    }
}

// This function is the one exported
void externalFoo(DArray!int intArray) {
    writeln("Calling extern foo");

    internalFoo(intArray);
}

// This function is the one you use
private void internalFoo(int[] intArray) {
    writeln("Calling internal foo");

    writeln(intArray);
}


void main() {
    // Constructing our test array
    DArray!int arrayTest;
    arrayTest.init(10);

    foreach (int i; 0 .. 10) {
        arrayTest.append(i);
    }

    // Testing the exported function 
    externalFoo(arrayTest);
}

Here is an absolute minimum version of how to do it

struct DArray(T) {
    T* data;
    size_t length;

    @property T[] array() {
        T[] arr;

        foreach(i; 0 .. length) {
            arr ~= data[i];
        }

        return arr;
    }

    alias array this;

}

// This function is the one exported
void externalFoo(DArray!int intArray) {
    writeln("Calling extern foo");

    internalFoo(intArray);
}

// This function is the one you use
private void internalFoo(int[] intArray) {
    writeln("Calling internal foo");

    writeln(intArray);
}
like image 133
Bauss Avatar answered Oct 10 '22 05:10

Bauss