Solved

passing VB.NET Strings to VC dll.

Posted on 2004-03-27
10
851 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

 
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

Quiz: What Do These Organizations Have In Common?

Hint: Their teams ended up taking quizzes, too.

Question has a verified solution.

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

Many of us here at EE write code. Many of us write exceptional code; just as many of us write exception-prone code. As we all should know, exceptions are a mechanism for handling errors which are typically out of our control. From database errors, t…
For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
In this video, viewers will be given step by step instructions on adjusting mouse, pointer and cursor visibility in Microsoft Windows 10. The video seeks to educate those who are struggling with the new Windows 10 Graphical User Interface. Change Cu…
If you’ve ever visited a web page and noticed a cool font that you really liked the look of, but couldn’t figure out which font it was so that you could use it for your own work, then this video is for you! In this Micro Tutorial, you'll learn yo…

729 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