Unmanged API's

Posted on 2004-08-05
Medium Priority
Last Modified: 2008-01-09
I been having issues with a 3rd party unmanaged DLL which I use to access a database via an api. I am trying to pass in a string value which the documentation states as a pointer (char*). I have next to no C++ experience so it could be a real obvious one !

the C++ api declaration reads as follows

// Assume TM1V is an int
TM1IMPORT TM1V TM1API TM1SystemServerHandle( TM1U hUser, CHAR * szName );

and is called in the demo client C++ app like so

LPSTR sServerName="testA";
TM1U hUser="1";

TM1SystemServerHandle( hUser, sServerName );

I found that using a C# string value for the second paramter was causing issues so I changed the API call to Marshal the value as LPSTR as follows

[DllImport("tm1api.dll")]  private static extern  int TM1SystemServerHandle  (int hUser ,[MarshalAs(UnmanagedType.LPStr)] string ipntName );

and called like follows

//assume huser is a valid handle
string mySting="testA"
StringBuilder sb=new StringBuilder(myString,255);
int ihTest = TM1SystemServerHandle(hUser, sb.ToString());

this produces the same issues (occasional null return) as when I passed the string in as of type string. I have also changing the api to accept a Stringbuilder and also IntPnt generated from Marshal.StringToHGlobalAnsi.

I sed to have similar issues when returning strings from the api but after some help I found that by returning an IntPnt and using Marshal.PtrToStringAnsi and it all worked fine.

Not sure what else to try. Is there any other was to handle pointers ?

thanks in advances

Question by:GillyTheTaffy
  • 4
  • 3
LVL 37

Expert Comment

ID: 11731504
sorry I missed this in your other question...

from  the previous link I gave you http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpcondefaultmarshalingforstrings.asp

In some circumstances, a fixed-length character buffer must be passed into unmanaged code to be manipulated. Simply passing a string does not work in this case because the callee cannot modify the contents of the passed buffer. Even if the string is passed by reference, there is no way to initialize the buffer to a given size.

The solution is to pass a StringBuilder buffer as the argument instead of a string. A StringBuilder can be dereferenced and modified by the callee, provided it does not exceed the capacity of the StringBuilder. It can also be initialized to a fixed length. For example, if you initialize a StringBuilder buffer to a capacity of N, the marshaler provides a buffer of size (N+1) characters. The +1 accounts for the fact that the unmanaged string has a null terminator while StringBuilder does not.

For example, the Microsoft Win32 API GetWindowText function (defined in Windows.h) is a fixed-length character buffer that must be passed into unmanaged code to be manipulated. LpString points to a caller-allocated buffer of size nMaxCount. The caller is expected to allocate the buffer and set the nMaxCount argument to the size of the allocated buffer. The following code shows the GetWindowText function declaration as defined in Windows.h.

int GetWindowText(
HWND hWnd,        // Handle to window or control.
LPTStr lpString,  // Text buffer.
int nMaxCount     // Maximum number of characters to copy.
A StringBuilder can be dereferenced and modified by the callee, provided it does not exceed the capacity of the StringBuilder. The following code example demonstrates how StringBuilder can be initialized to a fixed length.

[Visual Basic]
Public Class Win32API
Public Declare Auto Sub GetWindowText Lib "User32.Dll" _
(h As Integer, s As StringBuilder, nMaxCount As Integer)
End Class
Public Class Window
   Friend h As Integer ' Friend handle to Window.
   Public Function GetText() As String
      Dim sb As New StringBuilder(256)
      Win32API.GetWindowText(h, sb, sb.Capacity + 1)
   Return sb.ToString()
   End Function
End Class
public class Win32API {
public static extern void GetWindowText(int h, StringBuilder s,
int nMaxCount);
public class Window {
   internal int h;        // Internal handle to Window.
   public String GetText() {
      StringBuilder sb = new StringBuilder(256);
      Win32API.GetWindowText(h, sb, sb.Capacity + 1);
   return sb.ToString();

notice the different ... you are still passing a string here, not the stringbuilder ... you are passing sb.ToString() instead of just sb.



Author Comment

ID: 11731765
thanks again Greg, I tried passing the Stringbuilder, Stringbuilder.ToString() and string (also String) but all still produce the same problem.

The api call in question doesn't ask for a length or populate the Stringbuilder - it just returns a handle if successful or 0 if it ain't

see below
[DllImport("tm1api.dll")]  private static extern  int TM1SystemServerHandle  (int hUser ,StringBuilder sbName );
StringBuilder sb=new StringBuilder(sCatalog,256);
ihCatalog = TM1SystemServerHandle(hUser, sb);

I've tried the above with and without the MarshalAs..... paramters and still no joy. Pulling what little hair I have left out here as I've spent nearly a whole day on this on thing!

Could this possilby be an issue with the provider or is it definately just a .net issue.

thanks again (and again)

LVL 37

Expert Comment

ID: 11731771
is it modifying the string ?
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.


Author Comment

ID: 11731805
nope (nor should it)
LVL 37

Accepted Solution

gregoryyoung earned 500 total points
ID: 11731820
it should be of this form class StringLibAPI {
public static extern void PassLPStr([MarshalAs(UnmanagedType.LPStr)]
String s);

my guess is that another error is occurring occasionally ...


Author Comment

ID: 11731849
yeah thats what I tried last night and was pretty confident it would work. However it still produces the same problem.

I'll contact the vendors and see if they have any .net doco rather than C++

thanks for all your help
LVL 37

Expert Comment

ID: 11731915
eh I think it may be some sort of error in their .dll if the problem is inconsitant, I might ask them "can this method return null and why ?"

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

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.

Join & Write a Comment

Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
Watch the video to learn how one can deal with PST file corruption issue with an outstanding Kernel for Outlook PST Repair Tool easily. Using this tool, non-technical users can swiftly perform the repair process to restore their essential data witho…
To export Lotus Notes to Outlook PST or Exchange and Domino Server files to Exchange Server or PST files with ease, go for Kernel for Lotus Notes to Outlook conversion tool. Through the video, you can watch the conversion process. A common user with…

622 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