Program crashes when trying to wrap Miniaudio
I tried writing a simple program that uses CPPYY to use Miniaudio from Python. However, at some point it crashes and I have no idea why. I'm using Windows 10 64-bit, CPython 3.9.5 and here is a ZIP file containg my Python code, my copy of Miniaudio (up-to-date) and miniaudio_dll.dll (to rebuild "cl miniaudio_dll.c") problem.zip I don't just JIT compile miniaudio.h because it causes a compilation error. Sorry if I forgot something, but nearly empty laptop batteries wait for no one.
I don't currently have access to a Windows box (I've received a loaner Intel macbook to install VMWare, but haven't gotten around to do so yet), so can't run.
However, if you have any more direct description of how/where the code crashes, I might have some idea/guess.
It seems to crash on line 32: config.dataCallback = callback Can you try reproducing it on what ever you have access to? Miniaudio should be easy to compile cross-platform: gcc miniaudio_dll.c -shared Then instead of loading miniaudio.dll load miniaudio.so or whatever.
On 9/14/21, wlav @.***> wrote:
I don't currently have access to a Windows box (I've received a loaner Intel macbook to install VMWare, but haven't gotten around to do so yet), so can't run.
However, if you have any more direct description of how/where the code crashes, I might have some idea/guess.
-- You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub: https://github.com/wlav/cppyy/issues/10#issuecomment-919481340
The cause are these two lines in mini.py:
config.playback.SampleRate = 44100
config.capture.sampleRate = 44100
as neither structure has a sampleRate datamember, only config (top-level) has.
Not 100% sure what is going on yet, but it is clear that the offset returned for SampleRate is the offset in config and then an assignment happens C++-side into first playback, then capture. (cppyy does not use __slots__ for structs but keeps __dict__, so the expected behavior is a harmless, although perhaps puzzling, Python-side insertion in the dicts of playback and capture, not any transfer of data to C).
The code should be (drop the above two lines):
config.sampleRate = 44100
I'll dig a bit further to see what exactly is going on, but the above fix should get you going.
In Miniaudio, the sampleRate field is defined as: ma_uint32 sampleRate; So the name is sampleRate, but why are you telling me to use config.SampleRate instead? By the way, why aren't slots being used? Wouldn't it raise an exception when you incorrectly modify fields like this? Or do slots make it hard to convert between C and Python?
So the name is sampleRate, but why are you telling me to use config.SampleRate instead?
b/c I'm doing half a dozen things in parallel and don't have enough cycles to pay too much attention: I c&p-ed that SampleRate from playback.SampleRate whereas indeed the problematic one is capture.sampleRate.
Below is a standalone reproducer that should succeed, but doesn't. Seems to be caused by the structs being anonymous (if they are named, all works as expected),
import cppyy
cppyy.cppdef("""\
namespace StructInStruct {
struct Outer {
Outer() { fO = -77; inner.fI = -99; }
int fO;
struct {
int fI;
} inner;
};
int check(const Outer& p, int which) {
if (which == 1) return p.fO;
if (which == 2) return p.inner.fI;
return -1;
} }""")
ns = cppyy.gbl.StructInStruct
o = ns.Outer()
assert o.fO == -77
assert ns.check(o, 1) == -77
assert ns.check(o, 2) == -99
o.inner.fO = 42
assert ns.check(o, 1) == -77
assert ns.check(o, 2) == -99
assert hasattr(o.inner, 'fI')
o.inner.fI = 37
assert ns.check(o, 1) == -77
assert ns.check(o, 2) == 37
I noticed something weird about anonymous structs:
C:\py\git\miniaudio>python.exe Python 3.9.5 (tags/v3.9.5:0a7dcbd, May 3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information.
from cppyy import include, gbl include("miniaudio.h") True cfg = gbl.ma_context_config() dir(cfg) ['add', 'assign', 'bool', 'class', 'delattr', 'destruct', 'dict', 'dir', 'dispatch', 'doc', 'eq', 'format', 'ge', 'getattribute', 'getitem', 'gt', 'hash', 'init', 'init_subclass', 'invert', 'le', 'lt', 'module', 'mul', 'ne', 'neg', 'new', 'pos', 'python_owns', 'radd', 'reduce', 'reduce_ex', 'repr', 'rmul', 'rsub', 'rtruediv', 'setattr', 'sizeof', 'smartptr', 'str', 'sub', 'subclasshook', 'truediv', 'weakref', 'allocationCallbacks', 'alsa', 'coreaudio', 'custom', 'jack', 'logCallback', 'pLog', 'pUserData', 'pulse', 'threadPriority', 'threadStackSize'] dir(cfg.pulse) ['add', 'assign', 'bool', 'class', 'delattr', 'destruct', 'dict', 'dir', 'dispatch', 'doc', 'eq', 'format', 'ge', 'getattribute', 'getitem', 'gt', 'hash', 'init', 'init_subclass', 'invert', 'le', '__lifeline', 'lt', 'module', 'mul', 'ne', 'neg', 'new', 'pos', 'python_owns', 'radd', 'reduce', 'reduce_ex', 'repr', 'rmul', 'rsub', 'rtruediv', 'setattr', 'sizeof', 'smartptr', 'str', 'sub', 'subclasshook', 'truediv', 'weakref', 'allocationCallbacks', 'alsa', 'coreaudio', 'custom', 'jack', 'logCallback', 'pLog', 'pUserData', 'pulse', 'threadPriority', 'threadStackSize']
Notice how dir() returns the same both times even though it shouldn't.
On 9/14/21, wlav @.***> wrote:
Below is a standalone reproducer that should succeed, but doesn't. Seems to be caused by the structs being anonymous (if they are named, all works as expected),
import cppyy cppyy.cppdef("""\ namespace StructInStruct { struct Outer { Outer() { fO = -77; inner.fI = -99; } int fO; struct { int fI; } inner; }; int check(const Outer& p, int which) { if (which == 1) return p.fO; if (which == 2) return p.inner.fI; return -1; } }""") ns = cppyy.gbl.StructInStruct o = ns.Outer() assert o.fO == -77 assert ns.check(o, 1) == -77 assert ns.check(o, 2) == -99 o.inner.fO = 42 assert ns.check(o, 1) == -77 assert ns.check(o, 2) == -99 assert hasattr(o.inner, 'fI') o.inner.fI = 37 assert ns.check(o, 1) == -77 assert ns.check(o, 2) == 37-- You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub: https://github.com/wlav/cppyy/issues/10#issuecomment-919698361
Yes, it's clearly not functioning as it should. My best guess at this point is that the anonymous struct is treated the same way as an anonymous enum (which is transparently accessible in the parent class).
Fixed in repo.
Oops; commenting on wrong bug report. No, this one is NOT yet fixed ...