7

I have a static library. This library have the following function defined

int WriteData(LPTSTR s)

The sample to call the function is

LPTSTR s = (LPTSTR) L"Test Data";   
int n = WriteData(s);

WriteData return 0 on success and -1 on failure.

I am writing a dynamic DLL to export this function.

int TestFun(LPTSTR lpData)
{
   return  WriteData(lpData);
}

A C++ test application result

LPTSTR s = (LPTSTR) L"Test Data";   
TestFun(s);  //OK  return 0

LPTSTR s = (LPTSTR) "Test Data";    
TestFun(s);  //Fail  return -1

I have to call it from a c# application. I assume my DLL-Import signature would be:

        [DllImport("Test.dll")]
        private static extern int TestFun(String s);

My question is very simple How can i call it from .Net? As you can see i have control over

TestFun(LPTSTR lpData)

but no control over

WriteData(LPTSTR s)

Thanks everybody for their input. So far i am stuck on casting. I think my problem would be solved when i woul be able take input from user and write 2 line for casting in place of following line.

   LPTSTR s = (LPTSTR) L"Test Data"); //<= How can ii take input from user and 
    TestFun(s);  //OK  return 0
Manjoor
  • 4,091
  • 10
  • 43
  • 67
  • 5
    Using TCHAR made sense 10 years ago. No more, there is no non-Unicode operating system left you have to support. Make everything wchar_t and move on. – Hans Passant Nov 03 '10 at 12:31
  • What 'does not work' when you pass lpData to the WriteData function? – harper Nov 03 '10 at 15:33
  • What function is actually in the static library interface? What part are _you_ writing in you wrapper DLL? What interface are you expected to provide? – harper Nov 03 '10 at 15:54
  • The lib function returns 0 on success and -1 on failure. I detrmine success and failure baseed on output of the function. – Manjoor Nov 04 '10 at 04:57
  • How can we tell you what the problem is with your function if you don't show us the function? – CiscoIPPhone Nov 06 '10 at 10:57

5 Answers5

7

The L prefix makes the string a wchar_t string. You can use the Windows API function MultiByteToWideChar to convert an ANSI string to a wchar_t string.

harper
  • 13,345
  • 8
  • 56
  • 105
  • 7
    @Manjoor: You should really explain WHY it isn't working. These guys are trying to help you at no cost to you and with no benefit to them, and you are dismissing their efforts and making them feel like they are wasting their time because you're too damned lazy to tell them exactly why their solution doesn't work for you. – Platinum Azure Nov 05 '10 at 13:49
  • @Platinum Azure I am not that lazy :). I told it was not working because it was not working. Prooblem was solved. – Manjoor Nov 06 '10 at 17:23
  • 13
    @Manjoor: No, that's not good enough here. If you want people to spend time doing your work without you paying them, you owe it to them to describe what exactly is going wrong, what your expected output is, what your real output is, ESPECIALLY when you're replying to an answer. – Platinum Azure Nov 06 '10 at 21:16
6

The specific "function" to perform the L prefix is a macro TEXT() or _T(). (TEXT is defined by the Windows SDK, _T is an extension of the Microsoft C Runtime).

These functions automatically add the L prefix when your project is built with unicode support on (which is the default for new projects now in most MS Dev environments) - or leave it off for non unicode (or ansi) configured projects.

Don't do this cast:

LPTSTR s = (LPTSTR) L"ABC";   // Working fine
     WriteData(s);

If the project was ever configured for non Unicode, then L"ABC" would still be an array of wide-characters, but LPTSTR would become a pointer to an array of 8bit characters.

This is how to correctly assign a string to an Ansi, Unicode, or "Text" string. (Text can be Ansi or Unicode depending on project settings) (I left off the L because its redundant, and added a C, because string literals should be constant).

PCSTR p1 = "ABC";
PCWSTR p2 = L"ABC";
PCTSTR p3 = TEXT("ABC");
Chris Becke
  • 34,244
  • 12
  • 79
  • 148
  • 5
    How about you tell him what isn't working instead of putting the burden on him to guess??? He's taking time out of his day to answer your question for no cost to you. You could at least give him _some_ information. – Steve M Nov 03 '10 at 15:38
1

I think you're confused, as your function should work just fine:

int TestFun(LPTSTR lpData)
{
   return  WriteData(lpData); // Should be happy
}

But when you call your function, you'll have to be careful:

TestFun((LPTSTR) L"ABC"); // Will work fine
TestFun((LPTSTR) "ABC");  // Will not work

This is because "ABC" and L"ABC" are two different things. If you look at them in memory:

"ABC"  | 65 66 67 00
L"ABC" | 65 00 66 00 67 00 00 00

Edited to add:

There is nothing like L prefix in .Net

This is just wrong. I just opened "New Project->C++->CLR Console" in VisualStudio, and the first line is:

Console::WriteLine(L"Hello World");
egrunin
  • 24,650
  • 8
  • 50
  • 93
  • As i mentioned in my question, this is going to be dynamic dll. This dll would be called from a .Net application. There is nothing like L prefix in .Net – Manjoor Nov 04 '10 at 05:01
  • The dll export function 'TestFun'. Can you give me idea how can i call it from a C# application? This is dll-import [DllImport("Test.dll")] private static extern int TestFun(String s); – Manjoor Nov 04 '10 at 07:22
  • Thanks for effort, but i am calling it from C# for testing and it need to be called from easylanguage so i can't use L. – Manjoor Nov 06 '10 at 11:17
1

Try:

[DllImport("Test.dll")]
private static extern int TestFun([MarshalAs(UnmanagedType.LPTStr)] string s);

More information on marshaling with the MarshalAsAttribute on MSDN.

Joshua Rodgers
  • 5,317
  • 2
  • 31
  • 29
0

I would wrap your strings in the _T(...) macro. That way its portable between ANSI and UNICODE builds.

Note that you are using the portable string type - LPTSTR - note the T. It will change between ANSI and UNICODE based on build settings.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445