3

I'm trying to do the pocketsphinx tutorial in C# using pinvoke but get an AccessViolationException when I try to decode using ps_decode_raw().

        IntPtr ps = PocketSphinx.ps_init(config);
        IntPtr fh = Win32Util.fopen(@"goforward.raw", "rb");
        int rv = PocketSphinx.ps_decode_raw(ps, fh, "goforward", -1);

The functions are wrapped as follows

    //ps_decoder_t* ps_init(cmd_ln_t* config)
    [DllImport("pocketsphinx.dll",
        SetLastError = true,
        CallingConvention = CallingConvention.Cdecl)]
    public extern static IntPtr ps_init(
        IntPtr config);

    //int ps_decode_raw(ps_decoder_t *ps, FILE *rawfh, char const *uttid, long maxsamps);
    [DllImport("pocketsphinx.dll",
        SetLastError = true,
        CallingConvention = CallingConvention.Cdecl)]
    public extern static int ps_decode_raw(
        IntPtr ps,
        IntPtr rawfh,
        [MarshalAs(UnmanagedType.LPStr)] string uttid,
        int maxsamps);

    [DllImport("msvcrt.dll",
        SetLastError = true,
        CallingConvention = CallingConvention.Cdecl)]
    public extern static IntPtr fopen(
        [MarshalAs(UnmanagedType.LPStr)] string _Filename,
        [MarshalAs(UnmanagedType.LPStr)] string _Mode);

I wrapped C's fopen as well just because it was the quickest way I can think of implementing the tutorial.

I tried calling cmd_ln_retain on ps to make sure that ps wasn't causing the problem. (it wasn't). I also removed my debug code in the above.

I'm pretty sure something is up with the fopen but I'm not sure what.

Someone asked for the pocketsphinx log. https://justpaste.it/h52t

Rodrigo Cano
  • 105
  • 6

1 Answers1

2

You don't check for errors anywhere. And it's wrong to set SetLastError to true for these functions. They won't call SetLastError.

Your big problem though is that the library uses a particular instance of the C runtime, depending on how you built it. And your fopen import is from a different instance of the C runtime.

You'll need to add some code to the library that exposes functions to create and destroy FILE* objects. By doing that you'll get a FILE* made by the correct runtime.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I'll remove `SetLastError` those were added by pInvoker. I'm not sure how to test if you're right about the C runtime being incorrect. The DLL is the one in the system32 folder. I also wrapped `fgets()` to check if it was the `FILE*` and it worked leaving me more at a loss. I'm going to try wrapping `fseek()` to see if that causes any problems next. – Rodrigo Cano Sep 18 '14 at 14:28
  • 1
    You are just making it worse. Of course the other functions from system msvcrt are fine when passed a `FILE*` created with `fopen` from system msvcrt. That proves nothing. The problem is that your `pocketsphinx.dll` doesn't use the system msvcrt. It use a runtime from the MSVC you used to build the DLL. Why don't you do what I say? – David Heffernan Sep 18 '14 at 14:50
  • I had to use [dependency walker](http://www.dependencywalker.com/) to find out that pocketsphinx was compiling with MSVCR100D.DLL NOT msvcrt.dll and now it works. – Rodrigo Cano Sep 18 '14 at 15:23
  • 1
    There's more to it than this. You cannot redistribute the debug runtime. So as soon as you wish to redistribute this you'll need to switch to a release build, and you'll be back to where you are. The smart way to fix this is exactly as I state in my final paragraph. Add to the pocketsphinx.dll that you build some exports of the runtime functions you need. – David Heffernan Sep 18 '14 at 15:26