Solved

passing VB.NET Strings to VC dll.

Posted on 2004-03-27
10
847 Views
Last Modified: 2008-02-01
I want to pass a VB.NET string variable to my VC dll. The function in dll uses LPSTR.  why is it that i have to set the string to some initial value and then pass this string. This style works, but it is not a proper one. for example -

Dim str as String
str = "11111111111"

if i don't do this, i get an error of Nullreference ptr. this style is quite an improper one. if the new value put by the DLL is greater than the size specified, i.e., "11111111111",  then that value is truncated to the VB String size. if the new value filled in by DLL is less than initial size of "11111111111", then that much goes as a waste.

is there any other method to do this stuff. i've tried interop marshal concept  using Intptr. that too fails. Intptr works fine when i've a string inside a structure. but if that string goes individually, IntPtr fails. i don't understand why it fails here.

regards
0
Comment
Question by:rahul_milo
  • 5
  • 3
  • 2
10 Comments
 
LVL 48

Accepted Solution

by:
AlexFM earned 100 total points
ID: 10694997
Consider the following Dll function:

// Function gets const pointer to string
void CFunction(char* p)                    // == LPSTR
{
    MessageBox(NULL, p, NULL, MB_OK);
}

To call it from C#:

[DllImport ("ServerDll.dll")]
public static extern void CFunction(IntPtr p);

String s = "11111111111";

// allocate string on unmanaged heap
IntPtr ptr = Marshal.StringToHGlobalAnsi(s);

CFunction(ptr);

// free memory
Marshal.FreeCoTaskMem(ptr);

If C function gets UNICODE string paraneter (WCHAR*), use Marshal.StringToHGlobalUni. I hope you can translate this code to VB .NET without problems.
0
 
LVL 6

Expert Comment

by:KarunSK
ID: 10696437
It is not correct to pass a String type to a DLL if the DLL is going to change the value of the string. This is because String is an immutable object. So even if you are able to change the value (of which I am not sure), t may have other unwanted side effects.

You can use a StringBuilder or byte array in its stead. See if this link is helpful:

http://experts-exchange.com/Programming/Programming_Languages/Dot_Net/Q_20930937.html
0
 

Author Comment

by:rahul_milo
ID: 10702739
Thanks Alex,

It was gr8 as i cud declare a String s = "1" only use the same for all my config parameters. It worked fine and also returned the value greater than 1 byte.
 
what KarunSK has suggested that strings are immutable and their value cannot be changed inside a DLL. right or wrong. bcoz i'm able to do this without getting any error. may be an error creeps in some other time.

rahul.
0
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 
LVL 48

Expert Comment

by:AlexFM
ID: 10702809
Show your C function code. My way works to pass read-only string to Dll. If you change it, original string is not changed.
0
 

Author Comment

by:rahul_milo
ID: 10702863
Karun,

I must say, this was an add to my knowledge. lovely point made. my ques - if strings r immutable, then how come they r changed at the first instance. u said, may be later this may cause errors.

anyways, yr link was good to make me learn more on strings.
0
 

Author Comment

by:rahul_milo
ID: 10702902
Karun,

I was just going thru the MSDN link given by u. man, it was an eye opener. thanks. i'm getting a lot of callback problems. i hope avoiding string passing will stop this callback errors. i think the heap is getting destroyed bcoz of string passing. thanks

rahul
0
 

Author Comment

by:rahul_milo
ID: 10703201

__declspec(dllexport) int get_config(LPSTR key, LPSTR val)
{

      if ((idx=searchkey(key))<=Failure)
        ERROR ------
      else
          sprintf(val, "%s", key_arr[idx].ptr);   // ptr is a char*
                  or
          sprintf(val, "%d", *((int*)key_arr[idx].ptr));  // it'll be like this for integers.
}


0
 

Author Comment

by:rahul_milo
ID: 10703265
KarunSK,

There is some problem with the StringBuilder i used. There is no error in the code. but the value returned is not up to the mark. If u can see the same, i'll be grateful.

This is my VB function declaration -
Public Declare Function nyget_config Lib "c:\my_comm\mycomm.dll" (ByVal key As String, <System.Runtime.InteropServices.MarshalAsAttribute(Runtime.InteropServices.UnmanagedType.LPWStr)> ByVal value As System.Text.StringBuilder) As Integer
-----StringBuilder goes as ByVal in the prototype.-----------------------------

This function in the DLL wud search the KEY (1st parameter) and wud put the value for that key in 2nd parameter - value.

__declspec(dllexport) int get_config(LPSTR key, LPSTR val)
{

      if ((idx=searchkey(key))<=Failure)
        ERROR ------
      else
          sprintf(val, "%s", key_arr[idx].ptr);   // ptr is a char*
                  or
          sprintf(val, "%d", *((int*)key_arr[idx].ptr));  // it'll be like this for integers.
}
------------------------------------------------

Also, Form_Load Event has -
---------------------------------------
Dim value As New System.Text.StringBuilder("Hello", 50)
Dim s as String
Dim key as String = "UserID"

get_config(key, value)
s = shortPath.ToString()
---------------------------------------------

This doesn't get me the correct UserID. eg. 101@yahoo.com. It returns as -  "!&llo"
Also i tried  Dim value As New System.Text.StringBuilder(50). This returns NULL.


0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10703277
Define this function as:

public static extern int get_config(IntPtr key, IntPtr val);

key parameter is [in] for get_config function, work with by the way described in my first post.
val parameter is [in, out] for get_config function. Allocate space using Marshal.AllocHGlobal Method (Int32) method and call get_config. To read result written to this buffer by get_config use Marshal.PtrToStringAnsi Method.
0
 
LVL 6

Expert Comment

by:KarunSK
ID: 10705877
Rahul:
As the article by Eric Gunnerson states, using String to get back a value modified in unmanaged memory space will produce undesirable results.

As Alex states, passing a string object and changing it at the DLL will not cause the string to change. I am not sure what is happening at your end.

In your DLLImport statement, declare the second parameter (value as StringBuilder) as UnmanagedType.LPStr. Declaring as LPWStr will cause it to be interpreted as Unicode string, 2 chars wide. But as you know the C strings are 1-byte in width; this will cause a mismatch.

Karun.
0

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article describes relatively difficult and non-obvious issues that are likely to arise when creating COM class in Visual Studio and deploying it by professional MSI-authoring tools. It is assumed that the reader is already familiar with the cla…
In my previous two articles we discussed Binary Serialization (http://www.experts-exchange.com/A_4362.html) and XML Serialization (http://www.experts-exchange.com/A_4425.html). In this article we will try to know more about SOAP (Simple Object Acces…
This Micro Tutorial hows how you can integrate  Mac OSX to a Windows Active Directory Domain. Apple has made it easy to allow users to bind their macs to a windows domain with relative ease. The following video show how to bind OSX Mavericks to …
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

773 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question