passing VB.NET Strings to VC dll.

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
rahul_miloAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

AlexFMCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
KarunSKCommented:
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
rahul_miloAuthor Commented:
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
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

AlexFMCommented:
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
rahul_miloAuthor Commented:
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
rahul_miloAuthor Commented:
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
rahul_miloAuthor Commented:

__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
rahul_miloAuthor Commented:
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
AlexFMCommented:
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
KarunSKCommented:
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.