Calling DLL function from C# and char** parameter type

S

Siol

I'm trying to call a dll function from C# which has the following form:

int some_function(int count, char **arg1, char **arg2)

Which parameter type I need to use in C# for C++ char** type? I tried
byte[][] (array of byte[]) but I get error "There is no marshaling support
for nested arrays."


regards
Tomaz
 
N

Nicholas Paldino [.NET/C# MVP]

Tomaz,

Are the strings being read from, or are they being written to? If they
are being read from, you should be able to pass it as an array of strings,
and it should work.

If they are being written to, then you will have to declare the
parameters as IntPtrs, allocate the memory for them, and then marshal the
data yourself (don't forget to unallocate the memory).
 
R

Rudy Velthuis

Siol said:
I'm trying to call a dll function from C# which has the following
form:

int some_function(int count, char **arg1, char **arg2)

Which parameter type I need to use in C# for C++ char** type? I tried
byte[][] (array of byte[]) but I get error "There is no marshaling
support for nested arrays."

Probably something like:

[DllImport(yourdllname, CharSet=CharSet.Ansi)]
public static extern int some_function(int count,
string[] arg1, string[] arg2);

--
Rudy Velthuis http://rvelthuis.de

"Everyone is a genius at least once a year; a real genius has his
original ideas closer together."
-- Georg Lichtenberg (1742-1799)
 
T

Tomaz Koritnik

The strings are input parameters to the function (init parameters).

regards
Tomaz


Nicholas Paldino said:
Tomaz,

Are the strings being read from, or are they being written to? If they
are being read from, you should be able to pass it as an array of strings,
and it should work.

If they are being written to, then you will have to declare the
parameters as IntPtrs, allocate the memory for them, and then marshal the
data yourself (don't forget to unallocate the memory).


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Siol said:
I'm trying to call a dll function from C# which has the following form:

int some_function(int count, char **arg1, char **arg2)

Which parameter type I need to use in C# for C++ char** type? I tried
byte[][] (array of byte[]) but I get error "There is no marshaling
support for nested arrays."


regards
Tomaz
 
R

Rudy Velthuis

Tomaz said:
The strings are input parameters to the function (init parameters).

Then (string[] arg1, string[] arg2) will do.

--
Rudy Velthuis http://rvelthuis.de

"Analyzing humor is like dissecting a frog. Few people are
interested and the frog dies of it."
-- E. B. White (1899-1985)
 
T

TomazK

I tried with string[] but as soon as I call the function, whole application
terminates instantly with no error message. I haven't tried with
CharSet=CharSet.Ansi yet.



from MySQL specification the dll function looks like this: int
mysql_library_init(int argc, char **argv, char **groups)



my implementation:



[DllImport("libmysqld.dll")]
private static extern int mysql_server_init(int argc, string[] argv,
string[] groups);


{
string[] argv = new string[1];
argv[0] = "mysql_test";


string[] groups = new string[2];
groups[0] = "libmysqd_server";
groups[1] = "libmysqd_client";


mysql_server_init(0, argv, groups);
}



regards

Tomaz




Rudy Velthuis said:
Tomaz said:
The strings are input parameters to the function (init parameters).

Then (string[] arg1, string[] arg2) will do.

--
Rudy Velthuis http://rvelthuis.de

"Analyzing humor is like dissecting a frog. Few people are
interested and the frog dies of it."
-- E. B. White (1899-1985)
 
R

Rudy Velthuis

TomazK said:
[DllImport("libmysqld.dll")]
private static extern int mysql_server_init(int argc, string[] argv,
string[] groups);


{
string[] argv = new string[1];
argv[0] = "mysql_test";


string[] groups = new string[2];
groups[0] = "libmysqd_server";
groups[1] = "libmysqd_client";


mysql_server_init(0, argv, groups);
}

Assuming that argc is an argument count, it should probably not be 0,
and assuming that to each arg there is a group, you should probably
have argc=2, and also have two (2)strings in each array:

{
string[] argv = new string[2];
argv[0] = "mysql_test";
argv[1] = argv[0];

string[] groups = new string[2];
groups[0] = "libmysqd_server";
groups[1] = "libmysqd_client";

mysql_server_init(2, argv, groups);
}

Of course, I have no idea which strings are valid. Try to convert a C
or C++ example, if you have one, to C#.

--
Rudy Velthuis http://rvelthuis.de

"The object of war is not to die for your country but to make
the other bastard die for his."
-- General George Patton (1885-1945)
 
T

TomazK

Yes, argc is a count and it doesn't matter if I specify 2 or 0 or any other
number. It's the same in all cases.


regards
Tomaz


Rudy Velthuis said:
TomazK said:
[DllImport("libmysqld.dll")]
private static extern int mysql_server_init(int argc, string[] argv,
string[] groups);


{
string[] argv = new string[1];
argv[0] = "mysql_test";


string[] groups = new string[2];
groups[0] = "libmysqd_server";
groups[1] = "libmysqd_client";


mysql_server_init(0, argv, groups);
}

Assuming that argc is an argument count, it should probably not be 0,
and assuming that to each arg there is a group, you should probably
have argc=2, and also have two (2)strings in each array:

{
string[] argv = new string[2];
argv[0] = "mysql_test";
argv[1] = argv[0];

string[] groups = new string[2];
groups[0] = "libmysqd_server";
groups[1] = "libmysqd_client";

mysql_server_init(2, argv, groups);
}

Of course, I have no idea which strings are valid. Try to convert a C
or C++ example, if you have one, to C#.

--
Rudy Velthuis http://rvelthuis.de

"The object of war is not to die for your country but to make
the other bastard die for his."
-- General George Patton (1885-1945)
 
J

Jesse McGrew

I tried with string[] but as soon as I call the function, whole application
terminates instantly with no error message. I haven't tried with
CharSet=CharSet.Ansi yet.

from MySQL specification the dll function looks like this: int
mysql_library_init(int argc, char **argv, char **groups)

my implementation:

[DllImport("libmysqld.dll")]
private static extern int mysql_server_init(int argc, string[] argv,
string[] groups);

{
string[] argv = new string[1];
argv[0] = "mysql_test";

string[] groups = new string[2];
groups[0] = "libmysqd_server";
groups[1] = "libmysqd_client";

mysql_server_init(0, argv, groups);

}

The function might expect groups and/or argv to be null-terminated.
Try adding an extra item to the end of each array and setting it to
null.

Jesse
 
R

Rudy Velthuis

Jesse said:
The function might expect groups and/or argv to be null-terminated.
Try adding an extra item to the end of each array and setting it to
null.

Could be. Good idea. But then I wonder what argc does there. <g>
 
J

Jesse McGrew

Could be. Good idea. But then I wonder what argc does there. <g>

From the MySQL docs for this function at
http://dev.mysql.com/doc/refman/5.0/en/mysql-server-init.html it seems
there are two problems:

1. 'groups' is indeed supposed to be null-terminated. This is easy
enough to fix; just add a null at the end of the array.

2. Both 'argv' and 'groups' are stored by the library and used later.
This is a serious problem, because if you use P/Invoke marshaling, the
pointers that .NET passes to the function will become invalid as soon
as the function returns. When the library later tries to refer to argv
or groups, it'll find nothing but garbage there, causing unexpected
behavior or a crash.

If you're using MySQL 5.0.3 or later, try using mysql_library_init
instead - it makes an internal copy of argv and groups, so you can
keep using P/Invoke marshaling with no trouble (as long as you add a
null entry to the end of groups). Otherwise, you'll have to allocate
the memory yourself for the arrays and each string, to make sure the
pointers stay valid as long as your program is running.

Jesse
 

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