473,387 Members | 1,534 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Pass char* to C# callback function

SB
What is the proper way to pass a character array (char *) from a "C" dll to
a C# method (delegate) in my app? Getting the dll (which simulates a third
party dll) to call my delegate works fine. However, as soon as I try to add
any "char *" parameters, I start getting exceptions in my C# app.

So far I've tried (among others):
public delegate int Test(char[] version);
and
public delegate int Test(string version); // won't work because string is a
managed type I suppose
I've read many articles on sending data from C# to a C dll...but not much is
written about going the other way around. In short, I'm basically sending
the C dll a callback address...and the C dll is supposed to fire the
callback and pass back a char array....then my app needs to convert it to a
string to work with.

TIA!
sb
Nov 16 '05 #1
7 8459
"public delegate int Test(char[] version);"
doesn't work because char[] is managed as well!!!

Now, this might not be the best solution (it most probably isn't)!

How about open project properties and allow unsafe blocks,
and then do what you need in unsafe block with pointers:
<code>
unsafe
{
public delegate int Test(char* version);
//something else...
}
</code>

On Tue, 22 Feb 2005 21:01:05 -0500, SB <st********@yahoo.com> wrote:
What is the proper way to pass a character array (char *) from a "C" dll
to
a C# method (delegate) in my app? Getting the dll (which simulates a
third
party dll) to call my delegate works fine. However, as soon as I try to
add
any "char *" parameters, I start getting exceptions in my C# app.

So far I've tried (among others):
public delegate int Test(char[] version);
and
public delegate int Test(string version); // won't work because string
is a
managed type I suppose
I've read many articles on sending data from C# to a C dll...but not
much is
written about going the other way around. In short, I'm basically
sending
the C dll a callback address...and the C dll is supposed to fire the
callback and pass back a char array....then my app needs to convert it
to a
string to work with.

TIA!
sb


--
Regards,
Nurchi BECHED

P.S.
C makes it easy to shoot yourself in the foot;
C++ makes it harder, but when you do,
it blows away your whole leg."
--Bjarne Stroustrup
Nov 16 '05 #2
SB
Isn't it something that as soon as you hit Post, you have a new idea?

I think I'm a bit closer now. The code below works...sort of. I can access
the char array from my C# method now...however I don't seem to be getting
the right return value inside the C dll. I am also getting this exception:
"Attempted to read or write protected memory. This is often an indication
that other memory has been corrupted."...so something is still wrong. I've
checked the calling convention for the dll and it looks like it's set to
__cdecl (/Gd compiler switch)...which matches my DllImport (see below).
[DllImport("mytest.dll", EntryPoint = "MyEvent", SetLastError = true,
ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void MyEvent(ref MyEventData _ data);

....

public delegate int TestDelegate(IntPtr buffer);

....

public int Test(IntPtr buffer)
{
string s = Marshal.PtrToStringAnsi(buffer);
System.Windows.Forms.MessageBox.Show(s);
return 55; // this is just a test return value
}

The C dll (test dll) code looks like this:

extern "C" __declspec(dllexport) void MyEvent(MyEventData *data)
{
int i = data->Test("one");
...
}

TIA,
SB
Nov 16 '05 #3
SB
See my notes inline:

"Nurchi BECHED" <nu****@telus.net> wrote in message
news:opsmmpf5a0szpcyl@i865...
"public delegate int Test(char[] version);"
doesn't work because char[] is managed as well!!!

Yep..I knew that too...I guess I was just hoping the compiler would take
care of marshalling it properly. See my other post which has an updated
approach which I believe it heading in the right direction.
Now, this might not be the best solution (it most probably isn't)!

How about open project properties and allow unsafe blocks,
and then do what you need in unsafe block with pointers:
<code>
unsafe
{
public delegate int Test(char* version);
//something else...
}
</code>

I thought about using an unsafe block yesterday...but I'm convinced that
it's not necessary. I think I'm just doing something wrong. In addition,
the number of call backs in this dll is really about 60...that's a lot of
"unsafe" code blocks that would have to be written!

sb
Nov 16 '05 #4
SB
After a few more hours, I have narrowed the problem quite a bit. Inside the
C dll, if I try to access the callback directly through a reference that is
passed in, it works great. However, if I place a reference to the callback
inside a struct and pass that struct in by ref, I get exceptions...and the
return values are incorrect (stack issue?).

**** The "C" dll code ****
typedef int (CALLBACK *CallbackFunction)(char *version);
....
extern "C" __declspec(dllexport) void MyDllFunction(EventDataStruct *data,
char* buffer, CallbackFunction callbackfn)
{
int res = (*callbackfn)(buffer); // this line works great...no
problems
// int res = (data->MyCallbackFunction) (buffer); // this line
throws an exception every time...even though the debugger shows that this
points to the same address as the above line
...
}
********
**** C# CODE ****
[DllImport("mybot.dll")]
public static extern void MyDllFunction(ref EventDataStruct data, string
value, MyCallbackFunction callbackFn);
....
public delegate int MyCallbackFunction (string buffer);
....
private void testButton_Click(object sender, EventArgs e)
{
MyClass mc = new MyClass(); // class creates delegate of
MyCallbackFunction in constructor...to be used to pass in reference to dll
// the above class' constructor creates an instance of
MyCallbackFunction delegate...ie m_MyData.TestCallback= new
MyCallbackFunction (TestCallback);
MyDllFunction(ref mc.m_MyData, "abc", mc.m_MyData.TestCallback);
}
....
// ---- Callback code -----
public static int TestCallback(string buffer)
{
System.Windows.Forms.MessageBox.Show(buffer);
return 89;
}
********

I don't get it. The only difference between them is that one is a direct
reference that is passed in, and the second is passed in through a struct.

....not sure where to go from here...need sleep :) Hopefully I transcribed
everything write above.

sb
Nov 16 '05 #5
Try this:

typedef int (__stdcall *CallbackFunction)(char*);

"SB" <st********@yahoo.com> wrote in message
news:%2****************@TK2MSFTNGP15.phx.gbl...
After a few more hours, I have narrowed the problem quite a bit. Inside
the C dll, if I try to access the callback directly through a reference
that is passed in, it works great. However, if I place a reference to the
callback inside a struct and pass that struct in by ref, I get
exceptions...and the return values are incorrect (stack issue?).

**** The "C" dll code ****
typedef int (CALLBACK *CallbackFunction)(char *version);
...
extern "C" __declspec(dllexport) void MyDllFunction(EventDataStruct *data,
char* buffer, CallbackFunction callbackfn)
{
int res = (*callbackfn)(buffer); // this line works great...no
problems
// int res = (data->MyCallbackFunction) (buffer); // this line
throws an exception every time...even though the debugger shows that this
points to the same address as the above line
...
}
********
**** C# CODE ****
[DllImport("mybot.dll")]
public static extern void MyDllFunction(ref EventDataStruct data, string
value, MyCallbackFunction callbackFn);
...
public delegate int MyCallbackFunction (string buffer);
...
private void testButton_Click(object sender, EventArgs e)
{
MyClass mc = new MyClass(); // class creates delegate of
MyCallbackFunction in constructor...to be used to pass in reference to dll
// the above class' constructor creates an instance of
MyCallbackFunction delegate...ie m_MyData.TestCallback= new
MyCallbackFunction (TestCallback);
MyDllFunction(ref mc.m_MyData, "abc", mc.m_MyData.TestCallback);
}
...
// ---- Callback code -----
public static int TestCallback(string buffer)
{
System.Windows.Forms.MessageBox.Show(buffer);
return 89;
}
********

I don't get it. The only difference between them is that one is a direct
reference that is passed in, and the second is passed in through a struct.

...not sure where to go from here...need sleep :) Hopefully I transcribed
everything write above.

sb

Nov 16 '05 #6
Usually I just use a string type for passing char *. C doesn't have strings
but use character-arrays instead (don't we just love C#? ;-).
This has always woked fine in my case.

Otherwise, try the .interop newsgroup.

/Morten
Nov 16 '05 #7
SB
Unfortunately, I cannot change the C dll at all....many users use the dll in
other applications. As I mentioned, the functions are compiled with the /GD
switch...which (unless I'm wrong), means that if unspecified, the calling
convention will be __cdecl.

:(
sb

"Manu" <jo*****@knowledgepointsolutions.com> wrote in message
news:u$**************@TK2MSFTNGP12.phx.gbl...
Try this:

typedef int (__stdcall *CallbackFunction)(char*);

"SB" <st********@yahoo.com> wrote in message
news:%2****************@TK2MSFTNGP15.phx.gbl...
After a few more hours, I have narrowed the problem quite a bit. Inside
the C dll, if I try to access the callback directly through a reference
that is passed in, it works great. However, if I place a reference to
the callback inside a struct and pass that struct in by ref, I get
exceptions...and the return values are incorrect (stack issue?).

**** The "C" dll code ****
typedef int (CALLBACK *CallbackFunction)(char *version);
...
extern "C" __declspec(dllexport) void MyDllFunction(EventDataStruct
*data, char* buffer, CallbackFunction callbackfn)
{
int res = (*callbackfn)(buffer); // this line works great...no
problems
// int res = (data->MyCallbackFunction) (buffer); // this line
throws an exception every time...even though the debugger shows that this
points to the same address as the above line
...
}
********
**** C# CODE ****
[DllImport("mybot.dll")]
public static extern void MyDllFunction(ref EventDataStruct data, string
value, MyCallbackFunction callbackFn);
...
public delegate int MyCallbackFunction (string buffer);
...
private void testButton_Click(object sender, EventArgs e)
{
MyClass mc = new MyClass(); // class creates delegate of
MyCallbackFunction in constructor...to be used to pass in reference to
dll
// the above class' constructor creates an instance of
MyCallbackFunction delegate...ie m_MyData.TestCallback= new
MyCallbackFunction (TestCallback);
MyDllFunction(ref mc.m_MyData, "abc", mc.m_MyData.TestCallback);
}
...
// ---- Callback code -----
public static int TestCallback(string buffer)
{
System.Windows.Forms.MessageBox.Show(buffer);
return 89;
}
********

I don't get it. The only difference between them is that one is a direct
reference that is passed in, and the second is passed in through a
struct.

...not sure where to go from here...need sleep :) Hopefully I
transcribed everything write above.

sb


Nov 16 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Harri Pesonen | last post by:
How do I pass the calling C++ class reference (or anything) to a callback? My code is: static PyObject* emb_Set(PyObject *self, PyObject *args) { char *key, *value; if(!PyArg_ParseTuple(args,...
74
by: Peter | last post by:
Hi, So many times, I have seen compile warning: "you used a char* without initilize it", probably on the code like this: ------------ char* ptr; func(..., ptr); ----------
8
by: Ekim | last post by:
my question is as follows: I've got a DLL in which I have a method GetBuffer (this one is extern, exported, is called from outside this program) which shall pass a char-buffer to the...
16
by: Ekim | last post by:
hello, I'm allocating a byte-Array in C# with byte byteArray = new byte; Now I want to pass this byte-Array to a managed C++-function by reference, so that I'm able to change the content of the...
1
by: Lenn | last post by:
Hi, I am using .BeginInvoke to make an asynchronous call to a function, and passing in a AsyncCallback, so client gets notification when method completes, relevant code is provided below: ...
0
by: Stephen Walch | last post by:
I am writing a managed C++ app that calls a third party "C" library. One of the functions I need to call is a standard callback routine: I supply a "C" style callback function and a optional...
6
by: Minfu Lu | last post by:
I have a problem dealing with passing a function address to a COM callback. I use this COM function for communicating to a hardware. My original project was written in VB. I have converted it to...
1
by: Vikas | last post by:
Hi I have been browsing C struct to C# mapping emails on the newsgroups, but I haven't been able to find a solution to my problem. My C structure looks like this: struct myCstruct { char *...
9
by: =?Utf-8?B?RWR3YXJkUw==?= | last post by:
I would greatly appreciate some help on passing managed object into unmanaged code. I need to pass a reference (address of) of a managed class into unmanaged code (written by a thrid party). The...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.