473,378 Members | 1,478 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,378 software developers and data experts.

Help calling function from DLL and processing returned value (Can not marshal return value)

Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to
be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the
code so I only have the documentation.
I'm trying to call a function called z4date that, according to the docs,
returns the date as "an 8-byte character string in the "YYYYMMDD" format".
When I run it with this code I've written , I get "Can not marshal return
value".

My real concern is that, if I'm having trouble with these functions that
return simple data types, how am I going to interact with functions that
return user-defined data types?

This is what I've written in the class so far:

....
using System.Runtime.InteropServices;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")] /* Do I need to use
DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
....

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not
marshal return value"
return myDate();
}

Any help is appreciated.
Nov 15 '05 #1
9 2795
Angel,

You will not be able to do this. The reason that it doesn't work with
your definitions is because the pointer that is being returned by the
function is of an indeterminate nature. True, the documentation states that
it returns eight bytes, but there is nothing in the code that indicates that
is the case.

To get around this, you should declare your return type as an IntPtr,
and then pass that to the static PtrToStringAnsi method on the Marshal
class.

The only thing to be considerate of is the fact that the function
allocated memory and returned it. To prevent a leak, you will have to
dispose of the memory pointed to by the IntPtr. How you do this is
dependent on how the DLL allocates it, and will require another call through
P/Invoke.

Also, you do have to use the attribute for every declaration.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Angel" <none> wrote in message
news:u5**************@tk2msftngp13.phx.gbl...
Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to
be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the
code so I only have the documentation.
I'm trying to call a function called z4date that, according to the docs,
returns the date as "an 8-byte character string in the "YYYYMMDD" format".
When I run it with this code I've written , I get "Can not marshal return
value".

My real concern is that, if I'm having trouble with these functions that
return simple data types, how am I going to interact with functions that
return user-defined data types?

This is what I've written in the class so far:

...
using System.Runtime.InteropServices;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")] /* Do I need to use
DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
...

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not
marshal return value"
return myDate();
}

Any help is appreciated.

Nov 15 '05 #2
Hi Angel,
If your have *z4date* returning a string. How do you expect PInvoke to
marshal it as an array of bytes
Instead of declare the function as:
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern byte[] z4date();

try to declare it as:
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern string z4date();

If you need that byte array you should convert the string to that array. We
cannot expect the marshaler to convert from any to any type we want.
Yes, you have to use DllImport for each and any function that you import
from unmanaged library.
--
HTH
B\rgds
100

"Angel" <none> wrote in message
news:u5**************@tk2msftngp13.phx.gbl...
Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to
be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the
code so I only have the documentation.
I'm trying to call a function called z4date that, according to the docs,
returns the date as "an 8-byte character string in the "YYYYMMDD" format".
When I run it with this code I've written , I get "Can not marshal return
value".

My real concern is that, if I'm having trouble with these functions that
return simple data types, how am I going to interact with functions that
return user-defined data types?

This is what I've written in the class so far:

...
using System.Runtime.InteropServices;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")] /* Do I need to use
DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
...

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not
marshal return value"
return myDate();
}

Any help is appreciated.

Nov 15 '05 #3
Stoitcho,

The problem with declaring the return value as a string is that the
memory allocated on the heap for the string in the unmanaged realm will now
not be released correctly, and cause a memory leak.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Stoitcho Goutsev (100) [C# MVP]" <10*@100.com> wrote in message
news:eL**************@TK2MSFTNGP10.phx.gbl...
Hi Angel,
If your have *z4date* returning a string. How do you expect PInvoke to
marshal it as an array of bytes
Instead of declare the function as:
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern byte[] z4date();

try to declare it as:
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern string z4date();

If you need that byte array you should convert the string to that array. We cannot expect the marshaler to convert from any to any type we want.
Yes, you have to use DllImport for each and any function that you import
from unmanaged library.
--
HTH
B\rgds
100

"Angel" <none> wrote in message
news:u5**************@tk2msftngp13.phx.gbl...
Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the code so I only have the documentation.
I'm trying to call a function called z4date that, according to the docs,
returns the date as "an 8-byte character string in the "YYYYMMDD" format". When I run it with this code I've written , I get "Can not marshal return value".

My real concern is that, if I'm having trouble with these functions that
return simple data types, how am I going to interact with functions that
return user-defined data types?

This is what I've written in the class so far:

...
using System.Runtime.InteropServices;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")] /* Do I need to use
DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
...

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not marshal return value"
return myDate();
}

Any help is appreciated.


Nov 15 '05 #4
I had tried it before but I kept getting "Object reference not set to an
instance of an object" when I moved the return value of the function to a
string variable.I tried it without the static modifier and got the same
results.

[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]

public static extern string z4date();

....

public static string getDate()

{

string mystr;

mystr = z4date(); // error: Object reference not set to an instance
of an object

return mystr;

}

I'm trying with Nicholas' suggestion to see if it works.
Thanks.
"Stoitcho Goutsev (100) [C# MVP]" <10*@100.com> wrote in message
news:eL**************@TK2MSFTNGP10.phx.gbl...
Hi Angel,
If your have *z4date* returning a string. How do you expect PInvoke to
marshal it as an array of bytes
Instead of declare the function as:
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern byte[] z4date();

try to declare it as:
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern string z4date();

If you need that byte array you should convert the string to that array. We cannot expect the marshaler to convert from any to any type we want.
Yes, you have to use DllImport for each and any function that you import
from unmanaged library.
--
HTH
B\rgds
100

"Angel" <none> wrote in message
news:u5**************@tk2msftngp13.phx.gbl...
Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the code so I only have the documentation.
I'm trying to call a function called z4date that, according to the docs,
returns the date as "an 8-byte character string in the "YYYYMMDD" format". When I run it with this code I've written , I get "Can not marshal return value".

My real concern is that, if I'm having trouble with these functions that
return simple data types, how am I going to interact with functions that
return user-defined data types?

This is what I've written in the class so far:

...
using System.Runtime.InteropServices;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")] /* Do I need to use
DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
...

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not marshal return value"
return myDate();
}

Any help is appreciated.


Nov 15 '05 #5
Thanks for the help.
I think I understand what you're saying but since I'm pretty new with this
type of programming, how would that look like?
So far, I have:

[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern IntPtr z4date();

....

public static IntPtr getDate()

{

IntPtr ptr ;

ptr = z4date(); // ptr.ToString() = "2"

string str = Marshal.PtrToStringAnsi(ptr);

MessageBox.Show (str); //str is null

return str;

}

But the debugger tells me that str is null, so I know I'm doing something
wrong. If I don't move it to a string (eg. MessageBox.Show
(ptr.ToString());), it displays a "2".

Angel



"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in
message news:ul*************@TK2MSFTNGP11.phx.gbl...
Angel,

You will not be able to do this. The reason that it doesn't work with
your definitions is because the pointer that is being returned by the
function is of an indeterminate nature. True, the documentation states that it returns eight bytes, but there is nothing in the code that indicates that is the case.

To get around this, you should declare your return type as an IntPtr,
and then pass that to the static PtrToStringAnsi method on the Marshal
class.

The only thing to be considerate of is the fact that the function
allocated memory and returned it. To prevent a leak, you will have to
dispose of the memory pointed to by the IntPtr. How you do this is
dependent on how the DLL allocates it, and will require another call through P/Invoke.

Also, you do have to use the attribute for every declaration.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Angel" <none> wrote in message
news:u5**************@tk2msftngp13.phx.gbl...
Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the code so I only have the documentation.
I'm trying to call a function called z4date that, according to the docs,
returns the date as "an 8-byte character string in the "YYYYMMDD" format". When I run it with this code I've written , I get "Can not marshal return value".

My real concern is that, if I'm having trouble with these functions that
return simple data types, how am I going to interact with functions that
return user-defined data types?

This is what I've written in the class so far:

...
using System.Runtime.InteropServices;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")] /* Do I need to use
DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
...

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not marshal return value"
return myDate();
}

Any help is appreciated.


Nov 15 '05 #6

"Angel" <none> wrote in message
news:u5**************@tk2msftngp13.phx.gbl...
Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to
be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the
code so I only have the documentation.
I'm trying to call a function called z4date that, according to the docs,
returns the date as "an 8-byte character string in the "YYYYMMDD" format".
When I run it with this code I've written , I get "Can not marshal return
value".

My real concern is that, if I'm having trouble with these functions that
return simple data types, how am I going to interact with functions that
return user-defined data types?

This is what I've written in the class so far:

...
using System.Runtime.InteropServices;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")] /* Do I need to use
DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
...

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not
marshal return value"
return myDate();
}

Any help is appreciated.


Just go one step further and encapsulate calling your "C" functions within a
C++ managed wrapper class. Use that class to 'interact' with the rest of
your C# application. Remove your imports from your class above and place
them within the module/namespace. Create methods that then call your
external "C" functions.

The only real way to remain sane is to isolate the CTS from the C types and
don't try to half step. <g>

Question, is the DLL really written in 'C' and therefore using a cdecl
calling convention, or is it written using stdcall (a la Win API)? If you
are really accessing exported C then you have to use the extern "C"
attribute.

-ralph


Nov 15 '05 #7
Hi Nicholas,
You are right. It frees only memory allocated with CoTaskMemAlloc.
--
B\rgds
100

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in
message news:ub**************@TK2MSFTNGP10.phx.gbl...
Stoitcho,

The problem with declaring the return value as a string is that the
memory allocated on the heap for the string in the unmanaged realm will now not be released correctly, and cause a memory leak.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Stoitcho Goutsev (100) [C# MVP]" <10*@100.com> wrote in message
news:eL**************@TK2MSFTNGP10.phx.gbl...
Hi Angel,
If your have *z4date* returning a string. How do you expect PInvoke to
marshal it as an array of bytes
Instead of declare the function as:
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern byte[] z4date();

try to declare it as:
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern string z4date();

If you need that byte array you should convert the string to that array. We
cannot expect the marshaler to convert from any to any type we want.
Yes, you have to use DllImport for each and any function that you import
from unmanaged library.
--
HTH
B\rgds
100

"Angel" <none> wrote in message
news:u5**************@tk2msftngp13.phx.gbl...
Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to
be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the code so I only have the documentation.
I'm trying to call a function called z4date that, according to the
docs, returns the date as "an 8-byte character string in the "YYYYMMDD"

format". When I run it with this code I've written , I get "Can not marshal return value".

My real concern is that, if I'm having trouble with these functions that return simple data types, how am I going to interact with functions that return user-defined data types?

This is what I've written in the class so far:

...
using System.Runtime.InteropServices;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")] /* Do I need to use DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
...

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not marshal return value"
return myDate();
}

Any help is appreciated.



Nov 15 '05 #8

Hi Angel,

Thanks for posting in this community!!

I am monitoring this group. After reviewing your discussion in this post, I
think you meet the problem of P/invoke marshal.

I think you should follow Nicholas's suggestion to marshal the return value
as IntPtr. But, I think you may can not use Marshal.PtrToStringAnsi to
convert the value. Because the return value of z4date may be a character
array without a '\0' at the end of the array. So maybe you should read the
byte one by one(Use Marshal.ReadByte method). Like this:

//Test C function, which return value without a '\0' at the end of the
character array:
extern "C" __declspec(dllexport) char* RetAChar()
{
pChar = new char[8];
for(int i=0; i<=7; i++)
{
*pChar = 'd';
pChar++;
}
pChar -= 8;
return pChar;
}

[DllImport("DllDemo.dll", CharSet=CharSet.Ansi)]
private static extern IntPtr RetAChar();
private void button3_Click(object sender, System.EventArgs e)
{
IntPtr str=RetAChar();

byte b;
for(int i=0;i<8;i++)
{
b=Marshal.ReadByte(str);
Console.WriteLine(Convert.ToChar(b));
}
}

But as you stated, your problem should not related to this, can you show me
more information of your problem?

====================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Nov 15 '05 #9
Hi Angel,

Does my reply make sense to you?

Is your problem resolved? Please feel free to feedback. Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Nov 15 '05 #10

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

Similar topics

4
by: Jim Hubbard | last post by:
I have some C# code that is supposed to wrap the defrag APIs and I am trying to convert it to VB.Net (2003). But, I keep having problems. The C# code is relatively short, so I'll post it...
8
by: baustin75 | last post by:
Posted: Mon Oct 03, 2005 1:41 pm Post subject: cannot mail() in ie only when debugging in php designer 2005 -------------------------------------------------------------------------------- ...
1
by: dhornyak | last post by:
I have been banging my head against the wall for a while now, and can't seem to id the problem. I've been through a ton of posts and the code doesn't seem any different. Can anybody see it? When...
8
by: Berhack | last post by:
I am not too familiar with C# interop so please help me out. I need to call the following C function (in a DLL): // this creates an array of strings // LPTSTR is just char * void C_Func(LPTSTR...
5
by: SStory | last post by:
Hi all, I really needed to get the icons associated with each file that I want to show in a listview. I used the follow modified code sniplets found on the internet. I have left in...
1
by: Rahul | last post by:
Hi Everybody I have some problem in my script. please help me. This is script file. I have one *.inq file. I want run this script in XML files. But this script errors shows . If u want i am...
22
by: SQACSharp | last post by:
I'm trying to get the control name of an editbox in another window. The following code set the value "MyPassword" in the password EditBox but it fail to return the control name of the EditBox. ...
15
by: Jay | last post by:
I have a multi threaded VB.NET application (4 threads) that I use to send text messages to many, many employees via system.timer at a 5 second interval. Basically, I look in a SQL table (queue) to...
8
by: =?Utf-8?B?UHVjY2E=?= | last post by:
Hi, I'm using vs2005, .net 2, C# for Windows application. I use DllImport so I can call up a function written in C++ as unmanaged code and compiled as a dll us vs2005. My application is able to...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
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: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
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?

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.