By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,874 Members | 1,028 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,874 IT Pros & Developers. It's quick & easy.

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

P: n/a
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
Share this Question
Share on Google+
9 Replies


P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a

"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

P: n/a
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

P: n/a

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

P: n/a
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 discussion thread is closed

Replies have been disabled for this discussion.