Click here to Skip to main content
15,913,361 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hello everybody
i have developed a small program in c# that calls a function form a DLL (function originally have written by C++, i have not any problem in calling or sending data into function, i mean other functions works fine also this function does it's job but i think the returned value by parameter is not going to be marshaled properly so the parameters were null after execution.
please consider the following code that is original c++ function (in my DLL):

C++
__declspec(dllimport) int __stdcall ReadFile (int type, char* data1, char* data2, char* data3);

this method signature show a function that reads some data from a hardware and returns back them in data1, data2, data3 into my c# program, consider that i have not access to the source code of DLL to change it, anyway i must solve the problem in c# program.

i know there was 2 major way to deal with DLL, my approach is :

C#
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int ReadFile(int arg1, [MarshalAs(UnmanagedType.LPStr)] StringBuilder data1, [MarshalAs(UnmanagedType.LPStr)] StringBuilder data2, [MarshalAs(UnmanagedType.LPStr)] StringBuilder data3);

IntPtr dll = LoadLibrary("mydll.dll");

IntPtr readFileAdrs = GetProcAddress(dll, "ReadFile");
ReadFile read = (ReadFile)Marshal.GetDelegateForFunctionPointer(readFileAdrs, typeof(ReadFile));


StringBuilder d1 = new StringBuilder(100);
StringBuilder d2 = new StringBuilder(100);
StringBuilder d3 = new StringBuilder(100);
ReadFile(1, d1, d2, d3);

// here i expect to get data from d1,... but all of them are null or empty


i am completely sure that function(DLL) works fine (because it was tested in other environment like Delphi, C++) but in C# it does not returns the data and all parameters is null after execution.
actually i have tested other types instead of StringBuilder like char[], string , IntPtr, unit[] also i have test them with ref and out qualifier .

tanks in advance;
Posted
Updated 30-Jun-12 16:59pm
v3

1 solution

What are you doing? You should directly use P/Invoke on this function:

C#
using System.Runtime.InteropServices;

static class ImportedMethodSet {
    [DllImport(DllName, EntryPoint = "ReadFile", CallingConvention = CallingConvention.StdCall)]
    internal extern static int ReadFile(
        int type, //bad idea, better create some enumeration with matching type values
        [MarshalAs(UnmanagedType.LPStr)] StringBuilder data1,
        [MarshalAs(UnmanagedType.LPStr)] StringBuilder data2,
        [MarshalAs(UnmanagedType.LPStr)] StringBuilder data3);
}


Basically, that's it.

The entry point name could be mangled (please see http://en.wikipedia.org/wiki/Name_mangling[^]), so you need to write exact name as it is exported. You can see what exactly was exported using some binary dump application, such as "DUMPBIN.EXE" (you can start it using Visual Studio Command Prompt, please see: http://msdn.microsoft.com/en-us/library/c1h23y6c%28v=vs.100%29.aspx[^]).

—SA
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 1-Jul-12 14:13pm    
[OP commented:]

My approach was correct too, but my hardware was not working properly at that time so i have getting error so my approach was OK too, actually there are no difference between tow approach of loading the DLLs, both of them do same thing.
Sergey Alexandrovich Kryukov 1-Jul-12 14:15pm    
Thank you for this comment. I must admit that I stopped analyzing your code when I saw that it is just more complex then it has to be; but I never stated it was certainly wrong (if it was all wrong, you would more likely get a crash, not empty data).
So, are you saying your code works now, either way?
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900