Hello all, I'm completely new to Nim, but after having ridden a lot of tutorials, I completely fall in love with him.
For really being able to use it, I need a couple of libraries. Hopefully, all of them are available from C++ or already partially implemented.
I'm trying to use a large state-of-art library for Music Information Processing (Essentia). For now, I want to just load it dynamically, then I will try to understand how to create a good API.
I'm trying to use nimline for loading it dynamically. Below is my code, that should compute the spectrum of a random array. Here is an example from C++ to understand how the library works. Here, instead, the official documentation.
import nimline
import random
cppincludes("./essentia/src/")
cpplibpaths("./essentia/build/src/libessentia.so")
defineCppType(OutputBase, "essentia::standard::OutputBase", "essentia/algorithmfactory.h")
defineCppType(InputBase, "essentia::standard::InputBase", "essentia/algorithmfactory.h")
defineCppType(Algorithm, "essentia::standard::Algorithm", "essentia/algorithmfactory.h")
defineCppType(AlgorithmFactory, "essentia::standard::AlgorithmFactory", "essentia/algorithmfactory.h")
proc main() =
var FactoryType: AlgorithmFactory
let factory: CppRef[AlgorithmFactory] = FactoryType.instance().to(CppRef[AlgorithmFactory])
let spectrometer = factory.create("Spectrum").to(CppRef[Algorithm])
var spectrum: seq[float32]
var randArray: array[0..100, float32]
for i in 0..<randArray.len:
randArray[i] = rand(0.0..100.0)
spectrometer.output("spectrum").to(CppRef[InputBase]).set(spectrum).to(void)
spectrometer.input("spectrum").to(CppRef[InputBase]).set(randArray).to(void)
spectrometer.compute().to(void)
echo spectrum
main()
I get the following error at C++/C compile time:
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp: In function ‘void main__B027HVeEntcgpQ9b3jKwZeQ()’:
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:230:40: error: ‘essentia::EssentiaFactory<BaseAlgorithm>::EssentiaFactory() [with BaseAlgorithm = essentia::standard::Algorithm]’ is protected within this context
230 | essentia::standard::AlgorithmFactory FactoryType;
| ^~~~~~~~~~~
In file included from /home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:12:
./essentia/src/essentia/algorithmfactory.h:149:3: note: declared protected here
149 | EssentiaFactory() {}
| ^~~~~~~~~~~~~~~
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:235:78: error: no matching function for call to ‘tyObject_CppRef__uzjF6kB2mFZZbGG9cViAamA::tyObject_CppRef__uzjF6kB2mFZZbGG9cViAamA(essentia::EssentiaFactory<essentia::standard::Algorithm>&)’
235 | y = (tyObject_CppRef__uzjF6kB2mFZZbGG9cViAamA)(FactoryType.instance());
| ^
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:50:8: note: candidate: ‘tyObject_CppRef__uzjF6kB2mFZZbGG9cViAamA::tyObject_CppRef__uzjF6kB2mFZZbGG9cViAamA()’
50 | struct tyObject_CppRef__uzjF6kB2mFZZbGG9cViAamA {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:50:8: note: candidate expects 0 arguments, 1 provided
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:50:8: note: candidate: ‘constexpr tyObject_CppRef__uzjF6kB2mFZZbGG9cViAamA::tyObject_CppRef__uzjF6kB2mFZZbGG9cViAamA(const tyObject_CppRef__uzjF6kB2mFZZbGG9cViAamA&)’
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:50:8: note: no known conversion for argument 1 from ‘essentia::EssentiaFactory<essentia::standard::Algorithm>’ to ‘const tyObject_CppRef__uzjF6kB2mFZZbGG9cViAamA&’
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:50:8: note: candidate: ‘constexpr tyObject_CppRef__uzjF6kB2mFZZbGG9cViAamA::tyObject_CppRef__uzjF6kB2mFZZbGG9cViAamA(tyObject_CppRef__uzjF6kB2mFZZbGG9cViAamA&&)’
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:50:8: note: no known conversion for argument 1 from ‘essentia::EssentiaFactory<essentia::standard::Algorithm>’ to ‘tyObject_CppRef__uzjF6kB2mFZZbGG9cViAamA&&’
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:237:95: error: no matching function for call to ‘tyObject_CppRef__3L9aJJuGBh50W6K9cBuua6HA::tyObject_CppRef__3L9aJJuGBh50W6K9cBuua6HA(essentia::standard::Algorithm*)’
237 | t_CppRef__3L9aJJuGBh50W6K9cBuua6HA)((*factory.p).create(("Spectrum")));
| ^
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:53:8: note: candidate: ‘tyObject_CppRef__3L9aJJuGBh50W6K9cBuua6HA::tyObject_CppRef__3L9aJJuGBh50W6K9cBuua6HA()’
53 | struct tyObject_CppRef__3L9aJJuGBh50W6K9cBuua6HA {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:53:8: note: candidate expects 0 arguments, 1 provided
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:53:8: note: candidate: ‘constexpr tyObject_CppRef__3L9aJJuGBh50W6K9cBuua6HA::tyObject_CppRef__3L9aJJuGBh50W6K9cBuua6HA(const tyObject_CppRef__3L9aJJuGBh50W6K9cBuua6HA&)’
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:53:8: note: no known conversion for argument 1 from ‘essentia::standard::Algorithm*’ to ‘const tyObject_CppRef__3L9aJJuGBh50W6K9cBuua6HA&’
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:53:8: note: candidate: ‘constexpr tyObject_CppRef__3L9aJJuGBh50W6K9cBuua6HA::tyObject_CppRef__3L9aJJuGBh50W6K9cBuua6HA(tyObject_CppRef__3L9aJJuGBh50W6K9cBuua6HA&&)’
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:53:8: note: no known conversion for argument 1 from ‘essentia::standard::Algorithm*’ to ‘tyObject_CppRef__3L9aJJuGBh50W6K9cBuua6HA&&’
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:263:128: error: no matching function for call to ‘tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ::tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ(essentia::standard::OutputBase&)’
263 | Ref__SdQetZheNEfwTjB9cyvL0KQ)((*spectrometer.p).output(("spectrum"))));
| ^
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:56:8: note: candidate: ‘tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ::tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ()’
56 | struct tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:56:8: note: candidate expects 0 arguments, 1 provided
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:56:8: note: candidate: ‘constexpr tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ::tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ(const tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ&)’
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:56:8: note: no known conversion for argument 1 from ‘essentia::standard::OutputBase’ to ‘const tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ&’
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:56:8: note: candidate: ‘constexpr tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ::tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ(tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ&&)’
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:56:8: note: no known conversion for argument 1 from ‘essentia::standard::OutputBase’ to ‘tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ&&’
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:269:129: error: no matching function for call to ‘tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ::tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ(essentia::standard::InputBase&)’
269 | pRef__SdQetZheNEfwTjB9cyvL0KQ)((*spectrometer.p).input(("spectrum"))));
| ^
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:56:8: note: candidate: ‘tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ::tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ()’
56 | struct tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:56:8: note: candidate expects 0 arguments, 1 provided
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:56:8: note: candidate: ‘constexpr tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ::tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ(const tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ&)’
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:56:8: note: no known conversion for argument 1 from ‘essentia::standard::InputBase’ to ‘const tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ&’
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:56:8: note: candidate: ‘constexpr tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ::tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ(tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ&&)’
/home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp:56:8: note: no known conversion for argument 1 from ‘essentia::standard::InputBase’ to ‘tyObject_CppRef__SdQetZheNEfwTjB9cyvL0KQ&&’
Error: execution of an external compiler program 'gcc -c -w -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -D_FORTIFY_SOURCE=2 -I./essentia/src/ -I/usr/lib/nim -I/home/sapo/Develop/nim -o /home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp.o /home/sapo/.cache/nim/nimline_test_d/@mnimline_test.nim.cpp' failed with exit code: 1
I was in contact with the nimline developer by email and he suggested to use nim ptr in place of the CppRef and to use the nimline invokeFunction utility to call a global static methods.
The problem I have now is that I have a let my_algorithm: ptr Algorithm and I need to call its method input which accepts a string as argument (docs here.
If I do my_algorithm.input("spectrum") nim tries to execute input(my_algorithm, "spectrum") which obviously is not found in the library. How can I deal with this?
And an example for C++ vectors, it's pretty straightforward
It looks like you can call methods of Algorithm, so my_algorithm[].input("spectrum") would be my guess
Thanks! this solved many problems. I'm still trying to understand why I needed it. Is it something like C's (*my_algorithm).input("spectrum")?
Now the code is compilable and runnable, but it espects a n``std::vector<float>`` whre I can use nim's arrays or seqs. Any idea for a proper casting?
But it seems strange not being able to convert seq to vector
They have slightly different representation, and one is GC-ed the other is not (unless you compile with --gc:arc). Use copyMem if you want to transfer data from Nim seqs<->std::vector.