# Pass Numpy array to Compiled Code (Wolfram Engine, Wolfram Client, Python)

What List-like structures in Python can Wolfram Client handle and how can support for new structures be added?

In this answer I describe how to execute from Python, code in a Mathematica package that that has been compiled to C.

One such compiled function for test purposes is this:

compiledTestFunction2 =
Compile[{{n, _Real, 1}, {m, _Real, 1}},
Module[{},
Cross[n, m]
],
CompilationTarget->"C", "RuntimeOptions"->"Speed"];


(Cross[] is compilable). This function is called from Python by defining

compiledTestFunctionPython2 = session.function('compiledTestFunction2')


And the function is invoked as

compiledTestFunctionPython2(thing1, thing2)


Using Wolfram Language functions via Wolfram Client to Wolfram Engine we obtain a reference result:

thing1 = array.array('f', [1,2,3])
thing2 = array.array('f',[2,3.3,7])
session.evaluate(wl.Cross(thing1, thing2))

PackedArray([ 4.1, -1. , -0.7])


We obtain the correct answer if we define thing1 and thing2 as Python:

• Lists e.g. [1, 2, 3]
• Arrays e.g. array.array('f', [1, 2, 3])
• Tuples e.g. (1, 2, 3), and even
• Sets e.g. set([1, 2, 3]) despite the lack of ostensible order to sets

but Numpy arrays are not supported. Attempting to use a Numpy array such as

thing1 = np.array([1.0, 2.0, 3.0])


causes the compiled function to be returned unevaluated with the error:

Argument … at position 1 should be a rank 1 tensor of machine-size real numbers.

Questions What array types does Wolfram Client handle and could support for other structures such as Numpy arrays be added; if so, how? (The documentation says Numpy is supported, but does it work for compiled functions?)

And although PackedArray([...]) is returned by default, is there any choice in the matter?

Update on passing in 26/11/2019

By trying to force Numpy arrays to be of a particular data type, using

thing1 = np.array([1.0, 2.0., 3.0], dtype = np.float16)


we discover, from the Not Supported Error for dtype('float16'), that Wolfram Client serialisation (in \wolframclient\serializers\encoders\numpy.py) supports the following: int8, int16, int32, int64, uint8, uint16, uint32, uint64, float32, float64, complex64, complex128

However, no explicit float choices are acceptable to the compiled function.

It looks as though any existing numpy array must be coerced back to some other form, and after a few experiments it seems that the most efficient way is e.g.

thing1 = np.array([1.0, 2.0, 3.0], dtype = np.float64)
thing1 = array.array('d', thing1)


but the differences between array, list and tuple are small.

Update on receiving back 26/11/2019

According to the documentation here

By default, packed arrays are deserialized as list. Specify a consumer instance that supports NumPy arrays WXFConsumerNumpy

If one then prepares a session with

session = WolframLanguageSession(kernelLoc, consumer=WXFConsumerNumpy())


then my compiled function that returns a 1D (table) of reals appears back in Python as class 'wolframclient.utils.packedarray.PackedArray' - not numpy array. Why?

I have yet to find the list of deserializers.