Solved

passing VB.NET Strings to VC dll.

Posted on 2004-03-27
10
843 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
 
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
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

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

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

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…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
This video discusses moving either the default database or any database to a new volume.
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

705 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now