Calling C Dll, function prototype

G

Gaetano D'Aquila

Hi,
I must call a C dll that export this function:

void __stdcall leggimet(const char* fname, unsigned char* buf, unsigned long
bufSize, char* extraInfo, long* resp)

There is anyone that suggest me DLLImport C# sintax?
I try:

[DllImport("c:\\temp\\leggimet.dll",
CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall,
SetLastError=true)]
public void leggimet(string fName, StringBuilder buf, UInt32 bufSize,
StringBuilder extrainfo, ref Int32 resp);

but the DLL cannot open the file... It is an UNICODE problem?
Thank you
G
 
G

Gaetano D'Aquila

Hi,
Thank you.
I have tried your suggestion writing this code:

============== CUT HERE ==================
[DllImport("c:\\temp\\leggimet.dll",
CharSet=CharSet.Ansi,
CallingConvention=CallingConvention.StdCall,
SetLastError=true)]
public static extern void leggimet(string fName,
System.String buf,
System.UInt32 bufSize,
System.String extrainfo,
System.IntPtr resp);

private unsafe void button1_Click(object sender, System.EventArgs e)
{
System.UInt32 Buf_Size=1250*625;
string fName="c:\\temp\\BW__0500.HRM";
System.String buf=new System.String('\0',(int)(Buf_Size));
System.String extraInfo = new System.String('\0',256);
System.IntPtr pResp;
System.Int32 resp=20;

pResp=new System.IntPtr(&resp);

leggimet(fName,buf,Buf_Size,extraInfo,pResp);
}

============== CUT HERE ==================

but when the debug execute the dll call (leggimet) I obtain an exception of
type: System.NullReferenceException
Can you help me?
I would remeber you that the var buf, extraInfo and resp must be modified by
the DLL function...
Thank you very much.
G

Jackson Davis said:
Gaetano,

I got this to work using the following signature:
[DllImport("c:\\temp\\leggimet.dll",
CharSet=CharSet.Ansi,
CallingConvention=CallingConvention.StdCall,
SetLastError=true)]
public void leggimet(string fName,
System.String buf,
System.UInt32 bufSize,
System.String extrainfo,
System.IntPtr resp);

I did have to specify Ansi or the strings were not marshalled correctly.

Jackson Davis [MSFT]
rights. Use of included script samples are subject to the terms specified at
 
G

Guest

Alright, now I see what you are doing. It wasn't obvious which parameters were in, out and in/out. Pass StringBuilders for string that need to be marshalled as in/out. You need to initialize them to the maximum size before passing them in. Also, you should mark the IntPtr as out. In order to initialize the long*, I had to use the address keyword in an unsafe context.
---- Example driver (must be compiled with /unsafe ----
using System;
using System.Text;
using System.Runtime.InteropServices;

public class blah
{
[DllImport("C:\\temp\\test\\test.dll",
CharSet=CharSet.Ansi,
CallingConvention=CallingConvention.StdCall,
SetLastError=true)]
static extern void leggimet([In] String fName,
[Out] StringBuilder buf,
[In] UInt32 bufSize,
[Out]StringBuilder extrainfo,
[Out]IntPtr resp);

public static void Main()
{
uint bufSize = 10;
StringBuilder buf = new StringBuilder((int)bufSize);
StringBuilder extraInfo = new StringBuilder(10); // Whatever is the max size of extrainfo.
int resp;

unsafe {
leggimet("blah", buf, bufSize, extraInfo, new IntPtr(&resp));
}

System.Console.WriteLine(buf);
System.Console.WriteLine(extraInfo);
System.Console.WriteLine(resp);
}
}

-- Example dll source ----

#include <stdio.h>

void __stdcall leggimet(const char* fname,
unsigned char* buf,
unsigned long bufSizem,
char* extraInfo,
long* resp)
{
printf("%s\n", fname);
strcpy(buf, "Blah");
strcpy(extraInfo, "Blah2");
*resp = 10;
}
 
B

BMermuys

Hi,

Gaetano D'Aquila said:
Hi,
I must call a C dll that export this function:

void __stdcall leggimet(const char* fname, unsigned char* buf, unsigned long
bufSize, char* extraInfo, long* resp)

There is anyone that suggest me DLLImport C# sintax?
I try:

[DllImport("c:\\temp\\leggimet.dll",
CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall,
SetLastError=true)]
public void leggimet(string fName, StringBuilder buf, UInt32 bufSize,
StringBuilder extrainfo, ref Int32 resp);

Try it like this:

public static extern void leggimet(string fName, [In,Out] byte[] buf, uint
bufSize, StringBuilder extraInfo, ref int resp);

void test()
{
uint size = 1250*625;
byte[] buffer = new buffer[size];
string fName = "c:\\temp\\BW__0500.HRM";
StringBuilder extraInfo = new StringBuilder(256);
uint resp = 0;
leggimet ( fName, buffer, size, extraInfo, ref resp );
}


If you really want to use a string as buffer, then you can use a
stringbuilder and set charset to ansi, but it's more common to map an
unsigned char array to a byte array.

HTH,
Greetings
 
G

Gaetano D'Aquila

Hi,
I have tryed your code but I again obtain an Exception.
I'm working on this problem from about 1 week without result.
I have written the same procedure in C++ and it works correctly.
My C++ code is:
============== CUT ====================
typedef void (__stdcall *MYPROC)(char*, unsigned char*, unsigned long,
char*, long*);

HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;

char fName[256]="c:\\temp\\BW__0500.HRM\0";
long resp=20;
unsigned char buf[1250*625];
unsigned long bufSize=625*1250;
char extraInfo[256];

hinstLib = LoadLibrary("c:\\temp\\leggimet.dll"); // Get a handle to the
DLL module.
if (hinstLib != NULL) // If the handle is valid, try to get the function
address.
{
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "leggimet");
if (NULL != ProcAdd) // If the function address is valid, call the
function.
{
fRunTimeLinkSuccess = TRUE;
(ProcAdd) (fName,buf,bufSize,extraInfo,&resp);
}
}
============== CUT ====================
If you want, I can send you my test DLL (wich I haven't the source code) and
my C# project.
I cant see nobody solution.
Can you help me?
Thank you very much.


Jackson Davis said:
Alright, now I see what you are doing. It wasn't obvious which parameters
were in, out and in/out. Pass StringBuilders for string that need to be
marshalled as in/out. You need to initialize them to the maximum size before
passing them in. Also, you should mark the IntPtr as out. In order to
initialize the long*, I had to use the address keyword in an unsafe context.
---- Example driver (must be compiled with /unsafe ----
using System;
using System.Text;
using System.Runtime.InteropServices;

public class blah
{
[DllImport("C:\\temp\\test\\test.dll",
CharSet=CharSet.Ansi,
CallingConvention=CallingConvention.StdCall,
SetLastError=true)]
static extern void leggimet([In] String fName,
[Out] StringBuilder buf,
[In] UInt32 bufSize,
[Out]StringBuilder extrainfo,
[Out]IntPtr resp);

public static void Main()
{
uint bufSize = 10;
StringBuilder buf = new StringBuilder((int)bufSize);
StringBuilder extraInfo = new StringBuilder(10); // Whatever is the max size of extrainfo.
int resp;

unsafe {
leggimet("blah", buf, bufSize, extraInfo, new IntPtr(&resp));
}

System.Console.WriteLine(buf);
System.Console.WriteLine(extraInfo);
System.Console.WriteLine(resp);
}
}

-- Example dll source ----

#include <stdio.h>

void __stdcall leggimet(const char* fname,
unsigned char* buf,
unsigned long bufSizem,
char* extraInfo,
long* resp)
{
printf("%s\n", fname);
strcpy(buf, "Blah");
strcpy(extraInfo, "Blah2");
*resp = 10;
}
rights. Use of included script samples are subject to the terms specified at
 
G

Gaetano D'Aquila

Thank you for your response.
I have tried your solution but does not work.
When I execute leggimet(...) I obtain an exception:
System.NullReferenceException
Please see my last message in the newsgroup for more information.
Have another idea?
Thank you.

BMermuys said:
Hi,

Gaetano D'Aquila said:
Hi,
I must call a C dll that export this function:

void __stdcall leggimet(const char* fname, unsigned char* buf, unsigned long
bufSize, char* extraInfo, long* resp)

There is anyone that suggest me DLLImport C# sintax?
I try:

[DllImport("c:\\temp\\leggimet.dll",
CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall,
SetLastError=true)]
public void leggimet(string fName, StringBuilder buf, UInt32 bufSize,
StringBuilder extrainfo, ref Int32 resp);

Try it like this:

public static extern void leggimet(string fName, [In,Out] byte[] buf, uint
bufSize, StringBuilder extraInfo, ref int resp);

void test()
{
uint size = 1250*625;
byte[] buffer = new buffer[size];
string fName = "c:\\temp\\BW__0500.HRM";
StringBuilder extraInfo = new StringBuilder(256);
uint resp = 0;
leggimet ( fName, buffer, size, extraInfo, ref resp );
}


If you really want to use a string as buffer, then you can use a
stringbuilder and set charset to ansi, but it's more common to map an
unsigned char array to a byte array.

HTH,
Greetings

but the DLL cannot open the file... It is an UNICODE problem?
Thank you
G
 
B

BMermuys

Hi,

Gaetano D'Aquila said:
Thank you for your response.
I have tried your solution but does not work.
When I execute leggimet(...) I obtain an exception:
System.NullReferenceException

I've created a dll function with the same prototype and used the c# code I
posted and it works. The prototype isn't really that special. So I have no
idea why you get this error...

There was a typo in my reply but I guess you saw it : byte[] buffer = new
buffer[size] should offcourse be byte[] buffer = new byte[size].
Please see my last message in the newsgroup for more information.
Have another idea?

If you want mail relevant stuff to (e-mail address removed)

Greetings
Thank you.

BMermuys said:
Hi,

Gaetano D'Aquila said:
Hi,
I must call a C dll that export this function:

void __stdcall leggimet(const char* fname, unsigned char* buf,
unsigned
long
bufSize, char* extraInfo, long* resp)

There is anyone that suggest me DLLImport C# sintax?
I try:

[DllImport("c:\\temp\\leggimet.dll",
CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall,
SetLastError=true)]
public void leggimet(string fName, StringBuilder buf, UInt32 bufSize,
StringBuilder extrainfo, ref Int32 resp);

Try it like this:

public static extern void leggimet(string fName, [In,Out] byte[] buf, uint
bufSize, StringBuilder extraInfo, ref int resp);

void test()
{
uint size = 1250*625;
byte[] buffer = new buffer[size];
string fName = "c:\\temp\\BW__0500.HRM";
StringBuilder extraInfo = new StringBuilder(256);
uint resp = 0;
leggimet ( fName, buffer, size, extraInfo, ref resp );
}


If you really want to use a string as buffer, then you can use a
stringbuilder and set charset to ansi, but it's more common to map an
unsigned char array to a byte array.

HTH,
Greetings

but the DLL cannot open the file... It is an UNICODE problem?
Thank you
G
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top