Question

I'm wrapping a C DLL (which I only have .h's) and I'm stuck with "Attempted to read or write protected memory".

Info:

  • Windows 7 64-bit
  • DLL is 64-bit
  • C# App and Wrapper is 64-bit

Export Def:

#if defined(_WIN32) && !defined(__SYMBIAN32__)
#define EXP_API __cdecl
#else
    #if !defined(__SYMBIAN32__)
        #define EXP_API
    #else
        #define EXP_API EXPORT_C
    #endif
#endif

Here is the C header struct:

typedef struct bufferstrm bufferstrm_tt;

struct bufferstrm
{
  uint32_t  (EXP_API * bytes_usage)(bufferstrm_tt *bs);

  uint8_t * (EXP_API * get_stuff)(bufferstrm_tt *bs, uint32_t length);


  struct implstrm* some_struct;
};

int32_t EXP_API strmParser(struct bufferstrm_tt *bs);

My C# Wrapper:

[DllImport("Parser.dll", EntryPoint = "strmParser", CallingConvention = CallingConvention.Cdecl)]
public static extern int strmParser(ref bufferstrm bs);

// Delegates
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint BUFSTRM_bytes_usage(ref bufferstrm bs);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr BUFSTRM_get_stuff(ref bufferstrm bs, uint length);

[StructLayout(LayoutKind.Sequential)]
public struct bufferstrm
{
   public BUFSTRM_bytes_usage bytes_usage;

   public BUFSTRM_get_stuff get_stuff;

   public IntPtr some_struct;
}

[StructLayout(LayoutKind.Sequential)]
public struct implstrm
{
   public uint dummy;
}

public static uint test_bytes_usage(ref bufferstrm bs)
{
   return 0;
}

public static IntPtr test_get_stuff(ref bufferstrm bs, uint length)
{
   return IntPtr.Zero;
}

If I use it like this: [Attempted to read or write protected memory]

bufferstrm bs = new bufferstrm();
bs.bytes_usage = BUFSTRM_bytes_usage(test_bytes_usage);
bs.get_stuff = BUFSTRM_get_stuff(test_get_stuff);
implstrm testStruct = new implstrm();
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(testStruct)));
Marshal.StructureToPtr(testStruct, ptr, false);
bs.some_struct = ptr;

int hr = strmParser(ref bs);

If I don't set the callbacks it just returns the predicted hr value (which is missing stuff).

Anyone has any idea what am I doing wrong?

Thank you!

EDIT:

Enabling "Unmanaged Code Debuggin" I got "Access violation reading location 0xffffffffffffffff". Does this tell you guys anything?

Was it helpful?

Solution

The obvious mistake in your translation is in the third member of bufferstrm

struct implstrm* some_struct;

This is a pointer to a struct. Based on the name, this struct, provides the actual implementation of the stream. The bufferstrm struct wraps that raw stream with a buffering layer. At least, that's what the names suggest.

Now in the C# code, you translated some_struct as an in-line struct, rather than a pointer. That is obviously wrong. It should be:

public struct bufferstrm
{
   public BUFSTRM_bytes_usage bytes_usage;
   public BUFSTRM_get_stuff get_stuff;    
   public IntPtr some_struct;
}

You'll need to use Marshal.StructureToPtr to create this pointer.

Beyond that, it seems quite plausible that the two functions that you provide are implemented incorrectly. You've given any details of that the functions are expected to do. Perhaps get_stuff is not allowed to return a null pointer. There's no way for us to check any of that because you've only given the prototype of the functions, but omitted details of the semantic rules that the functions must obey.

So I suspect that the delegates you pass are incorrect. But only somebody with knowledge of what they are expected to do can understand how to correct them.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top