DLL and C#: DLLImport, Pointers, GCHandles, the "unsafe" context, paths, static constructors, ...

Some days ago I had to import a DLL Sony provides to optimize index and vertex buffers for the PS Vita.

But I only have a few months experience working with C# so a little bit of researching was required.

First of all I needed to declare the functions to import, I did it using DLLImport:

http://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspx

using System;
using System.Runtime.InteropServices;
...
class Whatever
{
     [DllImport("geekStuff.dll"), 
     EntryPoint="MyFunction", 
     CallingConvention=CallingConvention.Cdecl]
     void MyFunction(void* vtx_buffer)
}

Another important thing: The parameters. My Dll was originally written in c++, so I needed write the proper types that matches the C++ ones. This conversion table was quite useful:


The functions I needed to use had void* pointers, to retreive them I used GCHandles:


Vector3 [] vtx_buffer;
...
GCHandle gch = GCHandle.Alloc(vtx_buffer);
void* p_vtx_buffer = (void*)gch.AddrOfPinnedObject();
MyFunction(p_vtx_buffer);
...

Edit: If you modify the data allocated by the GCHandle you will probably have to call gch = GCHandle.Alloc(vtx_buffer); before using it again. This was causing an "AccessViolationException" in my app.

Using void* will cause an error, because pointers can only use in an unsafe context. Enclosing the code in an unsafe block will fix the problem:


Another thing to comment is the path to the DLL. You can either specify the full path to the dll in DllImport or  set the Path environment variable by calling Environment.SetEnvironmentVariable. I choosed the second way:

string path = Environment.GetEnvironmentVariable("Path");
path += "C:" + Path.DirectorySeparatorChar.ToString()
             + "whatever" 
             + Path.DirectorySeparatorChar.ToString();
Environment.SetEnvironmentVariable(path);

I think the right place to do this is the "Whatever" Static Constructor:

using System;
using System.Runtime.InteropServices;
...
class Whatever
{
     [DllImport("geekStuff.dll"), 
     EntryPoint="MyFunction", 
     CallingConvention=CallingConvention.Cdecl]
     void MyFunction(void* vtx_buffer)
     static Whatever()
     {
          string path = Environment.GetEnvironmentVariable("Path");
          path += "C:" + Path.DirectorySeparatorChar 
                       + "whatever" 
                       + Path.DirectorySeparatorChar;
          Environment.SetEnvironmentVariable(path);
     }
}

Now the only problem is the huge crash is happening somewhere in the code :o) I hope to find it tomorrow morning...

Comentarios

Entradas populares