Click here to Skip to main content
15,891,033 members
Please Sign up or sign in to vote.
2.00/5 (1 vote)
Hi everyone,
I have an issue with this conversion problem.
From a C# component I need to call a C++ Dll method:

C++
C#
extern "C"
    {
        __declspec(dllexport) bool getVal(LPTSTR& ab);
    }


In c# I define a string 'cd.

C#
C#
[DllImport("...dll")]


public static extern bool getVal(???);

private void Testbutton_Click(object sender, EventArgs e)
{
    string cd????


    getVal(??cd???)
);


Question:

How do I call, from C#, the method so that the string defined in the C++ LPTSTR variable is copied into the C# string variable?
I don't know how big the returned string can be.

** UPDATE**

This is the C++ method:

C++
C#
extern "C"
{
    __declspec(dllexport) bool getVal(LPTSTR& retVal);
}


this is how retVal is set:

C#
extern bool getVal(LPTSTR& retVal)
 {
.
.
.
    String^ val = sr->ReadLine();

    retVal = (LPTSTR)(Marshal::StringToHGlobalAnsi(val)).ToPointer();
.
.
.
    return true;
 }


I need help calling this method from C#.
Currently I have:

C#
C#
[DllImport("myLibrary.dll", CallingConvention = CallingConvention.Cdecl)]

public static extern bool getVal([MarshalAsAttribute(UnmanagedType.LPTStr)] out String retVal);

private void Testbutton_Click(object sender, EventArgs e)
{
    string myVal;


    getVal(out myVal)
);


what I get in myVal is garbage, like chinese chars (ANSI/Unicode issue??), not the value I can print out and read if, debugging the dll, I access the val C++ variable.
Maybe the conversion from String^ to LPTSTR is not correct?
Posted
Updated 22-Aug-15 9:08am
v3
Comments
Philippe Mori 20-Aug-15 21:33pm    
Follow the same pattern as Win32 API calls...

1 solution

By default, C string is marshaled as .NET string in P/Invoke. To be certain, you can use the attribute System.Runtime.InteropServices.MarshalAsAttribute:
https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshalasattribute%28v=vs.110%29.aspx[^].

The attribute should be applied to separate method parameter, as the target AttributeTargets.Parameter is supported (please see the attribute declaration above).

Say, for LPTSRT, you need to use https://msdn.microsoft.com/en-us/library/6e0wtfh2%28v=vs.110%29.aspx[^];
System.Runtime.InteropServices.UnmanagedType.LPTStr:
https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.unmanagedtype%28v=vs.110%29.aspx[^].

By the way, you don't have to use extern "C" just to have undercorated function name. Why not using default decorated (mangled) names directly (see https://en.wikipedia.org/wiki/Name_mangling[^])? You can find out exact decorated name using some binary dump utility, such as "dumpbin.exe" (https://msdn.microsoft.com/en-us/library/c1h23y6c.aspx[^], can be executed under the "Visual Studio Command Prompt") and use it directly in the EntryPoint named parameter (property) of System.Runtime.InteropServices.DllImportAttribute:
https://msdn.microsoft.com/en-us/library/Aa984739%28v=VS.71%29.aspx[^],
https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute%28v=vs.110%29.aspx[^],
https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.entrypoint(v=vs.110).aspx[^].

—SA
 
Share this answer
 
v2
Comments
CPallini 20-Aug-15 13:36pm    
5.
Sergey Alexandrovich Kryukov 20-Aug-15 14:04pm    
Thank you, Carlo.
—SA
Pietro_In_Milan 21-Aug-15 8:49am    
Sergey thanks for the prompt reply but I am still not able to get that value.
This is the C++ code and how I fill the out parameter
...
String^ val = sr->ReadLine();
ab = (LPTSTR)(Marshal::StringToHGlobalAnsi(val)).ToPointer();
ab is empty even though val correctly shows the string: how am I supposed to pass the "val" string as an out parameter? is LPTSTR& the best way to go?
Additionally, in C# how should I proceed?

public static extern bool getVal([MarshalAsAttribute(UnmanagedType.LPTStr)] String c);

Basically, how should I define the String in C# and how to use it to call the getVal C++ method and receive the string I am correctly reading, in the dll, from the streamreader instance sr?
A code excerpt would be great.
Thanks in advance,
Pietro
Sergey Alexandrovich Kryukov 21-Aug-15 10:25am    
This is not reply, this is a solution. :-) You got all you need. What you are doing in this code sample? You asked about using P/Invoke, I answered. If you don't understand something, the best way to understand is to try to write the C# code with P/Invoke, so, if you have some issue, I could see it.
—SA
Pietro_In_Milan 22-Aug-15 10:20am    
I just updated the question with the code. Summarizing, I need to know how to call this C++ method from C#:bool getVal(LPTSTR& retVal);
Thanks!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900