By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,906 Members | 1,750 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,906 IT Pros & Developers. It's quick & easy.

C#-APP: problem with DllImport when string not the first param

P: 2
I have a simple Win32 DLL I wrote named "SimpleLib" that exports two functions. It is written in C++ and compiled with __stdcall (/Gz) and with the preprocessor definition _MBCS (not Unicode).

The first function is called "StrFirst" and takes in a LPTSTR as the first parameter and a long as the second, like this:
Expand|Select|Wrap|Line Numbers
  1. SIMPLELIB_API int StrFirst(LPTSTR str, long num);
The second function is essentially the same thing, but with the order of the parameters switched. It is called "LongFirst" and takes in a long as the first param and a LPTSTR as the second param, like this:
Expand|Select|Wrap|Line Numbers
  1. SIMPLELIB_API int LongFirst(long num, LPTSTR str);
The implementation inside these functions simply displays the values passed in. Nothing clever.

I also have a Win32 Console Application that calls these functions in the DLL, like this:
Expand|Select|Wrap|Line Numbers
  1. int _tmain(int argc, _TCHAR* argv[])
  2. {
  3.    LPTSTR MyStr = _T("Calling from TestApp");
  4.    long MyNum = 1234;
  5.    int RetVal = 1;
  6.    RetVal = StrFirst(MyStr, MyNum);
  7.    RetVal = LongFirst(MyNum, MyStr);
  8.    return 0;
  9. }
Everything so far works fine. The DLL sees the parameters in both functions without problem.

Now for the fun part! I also have a C# application that calls these two functions in the DLL. Calling the function that has the String as the first argument works fine. But calling the function with the String as the second argument fails. The DLL sees this second parameter as a null argument (not just an empty string, but actually as a zero value). Any idea why this function fails, while the other succeeds?

Here's the source:

Expand|Select|Wrap|Line Numbers
  1. using System.Runtime.InteropServices;   // DllImport
  2. namespace TestApp.Net
  3. {
  4.     class Program
  5.     {
  6.         static void Main(string[] args)
  7.         {
  8.             string str = "Calling from TestApp.Net";
  9.             long num = 1234;
  10.             int RetVal = 1;
  11.  
  12.             // The following call succeeds:
  13.             RetVal = StrFirst(str, num);
  14.  
  15.             // But this fails. The 2nd arg appears in the DLL as a NULL. Why?
  16.             RetVal = LongFirst(num, str);
  17.         }
  18.  
  19.         [DllImport("SimpleLib.dll")]
  20.         public static extern int StrFirst(string str, long num);
  21.  
  22.         [DllImport("SimpleLib.dll")]
  23.         public static extern int LongFirst(long num, string str);
  24.     }
  25. }
By the way, I wondered if this was a Unicode to ANSI marshalling problem, so I rebuilt the DLL as Unicode, and modified the two DllImport attributes to include CharSet=CharSet.Unicode. The same erroneous behavior occurs.

Any ideas?

thanks,
--John.
Nov 26 '08 #1
Share this Question
Share on Google+
1 Reply


P: 2
I found the answer to my problem! The numeric parameter in the DLL is declared as a long, which is a 32-bit integer. That same numeric parameter in the DllImport declaration is also declared as a long. However, its size in C# is actually a 64-bit integer (twice as big). So when this was passed as the first parameter, it passed in a 64-bit value, followed by the string. When the DLL read in the argument list, it read the first 32 bits, followed by the remaining 32-bits (which were zero), mistakenly thinking it was the string. Ouch!

Here's how they should have been declared in the C# code:

// "num" is declared as a long (32-bit int) in the DLL, but this is
// declared as an int (32-bit int) here in C#:
[DllImport("SimpleLib.dll")]
public static extern int StrFirst(string str, int num);
[DllImport("SimpleLib.dll")]
public static extern int LongFirst(int num, string str);
Nov 26 '08 #2

Post your reply

Sign in to post your reply or Sign up for a free account.