0

I am quite new to C# and I have build a class ProcessData that wraps a C++ DLL from manufacturer (I can't access to the code in this DLL). One of the method of the C++ DLL return a pointer (void far*) to a HandleFile.xyz that is on my hard drive but the content of this file is unknown to me. Another method re-use this pointer do process my data, as you can see in the code below.

    public class ProcessData
{

    [DllImport("myfile.dll", EntryPoint = "LoadFile", SetLastError = true, CharSet = CharSet.None)]
    public static extern IntPtr dLoadFile(string filePath);

    [DllImport("myfile.dll", EntryPoint = "WorkWithFile", SetLastError = true, CharSet = CharSet.None)]
    public static extern uint dWorkWithFile(IntPtr fileHandle, int mydata);

    public IntPtr currentFileHandle; 

    public void LoadFile(string filePath)
    {
    currentFileHandle = dLoadFile(filePath);
    }

    public uint WorkWithFile(int mydata)
    {
    uint x = dWorkWithFile(currentFileHandle, mydata);
    return x;
    }
}

If I try this when loading a single HandleFile.xyz, everything works well and the value returned by WorkWithFile makes sense.

The problem comes when I try to use ProcessData in another class as a List, because at the end, I need to process my data using multiple different HandleFile1.xyz, HandleFile2.xyz, HandleFile3.xyz that are loaded successively using different ProcessData object in a foreach loop. Each ProcessData object contains only the pointer to the corresponding HandleFileX.xyz.

The first iteration of the loop goes well, but the second iteration crashes on dWorkWithFile(currentFile, mydata) returning the following error:

Exception thrown at 0x07DE4C2A (myfile.dll) in MyProgram.exe: 0xC0000005: Access violation reading location 0x00000000.

I am suspecting that this might have to do with the way I initialize my pointer when creating the ProcessData objects as this post might suggest: https://stackoverflow.com/a/10479020/8298327

Is currentFileHandle = dLoadFile(filePath); the proper way to initialize my pointer or should I use some Marshalling, and if yes, how ? Could you provide an example?

Any other idea what could cause this issue?

bricx
  • 593
  • 4
  • 18
  • When you call a method the parameter list goes on the execution stack. When you return from the method the stack is disposed so you must allocate memory for a return pointer before you call the method. Or the c++ code must allocate memory not on the execution stack (like use the Windows Allocate function). – jdweng Feb 28 '19 at 23:01
  • What is currentFileHandle value when it crashes. It may be null. From the error message it looks like it is returning zero. Are you every closing the file between the first call and the second call? – jdweng Feb 28 '19 at 23:07
  • Hi jdweng, how can I allocate memory to the returned pointer if I don't know its size ? – bricx Feb 28 '19 at 23:43
  • jdwend, the currentFileHandle value when it crashes is not null, it is something like 0x0aaf1520. And yes, I am unloading the HandleFile.xyz between calls. Should I also "close" the DLL ? And if yes, how can I do that ? Thanks for your help! – bricx Feb 28 '19 at 23:46
  • Sorry, I was unloading the .xyz after processing but not after initialization... problem is now fixed. That's still strange that I could load all of them at initialization without any error. Thanks a lot for your comments jdweng. – bricx Mar 01 '19 at 00:32
  • A few ways 1) Make the size large enough to handle the worse case size of the returned data 2) Use the Windows Allocate method 3) Call dll twice with two different methods. First time return size. Then Allocate enough memory to return the size. Then call dll again to get actual data. – jdweng Mar 01 '19 at 09:50

1 Answers1

0

Ok, if anyone runs into this issue, you need to Unload the .xyz file after each iteration in the foreach loop using the UnFileLoad method.

public void UnLoadFile(IntPtr currentFileHandle)
{
uint = dUnLoadFile(currentFileHandle);
}

And that's what I was doing when processing the ProcessData objects. However I had also a method to Initialize the ProcessData objects and there I was not UnLoading the files. I could Initialize all my objects without problem (which is strange) but the program crashed when starting the processing.

Thanks to jdweng for the advices!

bricx
  • 593
  • 4
  • 18