Mixing Strings

  • Thread starter Thread starter Graeme Bell
  • Start date Start date
G

Graeme Bell

How can I mix std::wstring and .NET String? I'm finding the .NET
documentation frustrating.

Graeme
 
Graeme Bell said:
How can I mix std::wstring and .NET String? I'm finding the .NET
documentation frustrating.

Break into two problems:

(1) Convert between wchar_t* and std::wstring
Solution: wstring constructor and c_str() member

(2) Convert between wchar_t* and System::String^
Solution: PtrToStringChars and Marshal::PtrToStringUni
 
Jochen Kalmbach said:
Hi Graeme!

You can. But why?

Because .NET is one very small portion of the world? Because there is a lot
of existing C++ code that is standard compliant, therefore using
std::basic_string for string handling, which you might want to call from
..NET?
 
Hi Ben!
Because .NET is one very small portion of the world? Because there is a lot
of existing C++ code that is standard compliant, therefore using
std::basic_string for string handling, which you might want to call from
..NET?

Interop is always time consuming... so if you need it, you can do it.
But if you can prevent it, prevent it...

--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/
 
Hi Ben,

Ben Voigt said:
Break into two problems:

(1) Convert between wchar_t* and std::wstring
Solution: wstring constructor and c_str() member

(2) Convert between wchar_t* and System::String^
Solution: PtrToStringChars and Marshal::PtrToStringUni

Thanks for your helpful suggestion. I'll check out the docs. :)

Graeme
 
Hi Jochen,

I agree that interoperability is time-consuming - I'd rather not have to do
it at all, let alone by hand! However, when reusing cross-platform, standard
compliant libraries, you don't always get the choice of interface. Saying
"You didn't want to do that ..." doesn't help.

Graeme
 
Graeme Bell said:
Hi Jochen,

I agree that interoperability is time-consuming - I'd rather not have to
do it at all, let alone by hand! However, when reusing cross-platform,
standard compliant libraries, you don't always get the choice of
interface. Saying "You didn't want to do that ..." doesn't help.

He was referring to "Interop", the name of a very specific technology for
..NET that encompasses P/Invoke and C++/CLI "It Just Works". IJW is actually
very straight-forward and efficient compared to P/Invoke, so really it is
P/Invoke you should avoid.
 
Ben Voigt said:
He was referring to "Interop", the name of a very specific technology for

Looking again, maybe he wasn't.
.NET that encompasses P/Invoke and C++/CLI "It Just Works". IJW is
actually very straight-forward and efficient compared to P/Invoke, so
really it is P/Invoke you should avoid.

And this isn't really very relevant to dealing with string. Sorry for the
OT post.
 
Hi Ben!
He was referring to "Interop", the name of a very specific technology for
..NET that encompasses P/Invoke and C++/CLI "It Just Works". IJW is actually
very straight-forward and efficient compared to P/Invoke, so really it is
P/Invoke you should avoid.

???

What is the difference between "IJW" and "P/Invoke" in matter of
performance?

The only big difference is that you do not need to declare the
"DllImport" and "SuppressUnmanagedCodeSecurity" attribut.

But if you compare (on IL-level) a IJW-Call with an DllImport-call it is
the same!
In some cases P/Invoke is faster than IJWs! (as seen in my example: the
IJWs layer is generating the "SetLastError"-attribute, which is useless
in this context).

Simple-Example:
#include <windows.h>

namespace Foo
{
public ref class Bar
{
public:
static DWORD IJW()
{
return GetVersion();
}
static DWORD PInvoke()
{
return GetVersion_PInvoke();
}

private:
[System::Runtime::InteropServices::DllImport("kernel32.dll",
EntryPoint="GetVersion")]
[System::Security::SuppressUnmanagedCodeSecurity]
static DWORD GetVersion_PInvoke();
};
}
int main()
{
System::Console::WriteLine(Foo::Bar::IJW().ToString());
System::Console::WriteLine(Foo::Bar::PInvoke().ToString());
}


The generated code for IJW is (C#-syntax):
private uint modopt(IsLong) IJW()
{
return GetVersion();
}
The generated code for "GetVersion" is:
[MethodImpl(MethodImplOptions.Unmanaged,
MethodCodeType=MethodCodeType.Native), SuppressUnmanagedCodeSecurity,
DllImport("", EntryPoint="",
CallingConvention=CallingConvention.StdCall, SetLastError=true)]
public static extern uint modopt(IsLong) modopt(CallConvStdcall)
GetVersion();


The generated code for PInvoke is:
private uint modopt(IsLong) PInvoke()
{
return GetVersion_PInvoke();
}
The generated code for "GetVersion_PInvoke" is:
[MethodImpl(MethodImplOptions.ForwardRef),
SuppressUnmanagedCodeSecurity, DllImport("kernel32.dll",
EntryPoint="GetVersion")]
private static extern uint modopt(IsLong) GetVersion_PInvoke();



Of course, I had not verified what the JIT-compiler is doing with this
attributes... but I assume that IJW is at least as time consimung as the
DLLImport-way.

--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/
 
Jochen Kalmbach said:
Hi Ben!
He was referring to "Interop", the name of a very specific technology for
..NET that encompasses P/Invoke and C++/CLI "It Just Works". IJW is
actually very straight-forward and efficient compared to P/Invoke, so
really it is P/Invoke you should avoid.

???

What is the difference between "IJW" and "P/Invoke" in matter of
performance?
http://msdn2.microsoft.com/en-us/library/ky8kkddw(VS.80).aspx


The only big difference is that you do not need to declare the "DllImport"
and "SuppressUnmanagedCodeSecurity" attribut.

But if you compare (on IL-level) a IJW-Call with an DllImport-call it is
the same!
In some cases P/Invoke is faster than IJWs! (as seen in my example: the
IJWs layer is generating the "SetLastError"-attribute, which is useless in
this context).

Simple-Example:
#include <windows.h>

namespace Foo
{
public ref class Bar
{
public:
static DWORD IJW()
{
return GetVersion();
}
static DWORD PInvoke()
{
return GetVersion_PInvoke();
}

private:
[System::Runtime::InteropServices::DllImport("kernel32.dll",
EntryPoint="GetVersion")]
[System::Security::SuppressUnmanagedCodeSecurity]
static DWORD GetVersion_PInvoke();
};
}
int main()
{
System::Console::WriteLine(Foo::Bar::IJW().ToString());
System::Console::WriteLine(Foo::Bar::PInvoke().ToString());
}


The generated code for IJW is (C#-syntax):
private uint modopt(IsLong) IJW()
{
return GetVersion();
}
The generated code for "GetVersion" is:
[MethodImpl(MethodImplOptions.Unmanaged,
MethodCodeType=MethodCodeType.Native), SuppressUnmanagedCodeSecurity,
DllImport("", EntryPoint="", CallingConvention=CallingConvention.StdCall,
SetLastError=true)]
public static extern uint modopt(IsLong) modopt(CallConvStdcall)
GetVersion();


The generated code for PInvoke is:
private uint modopt(IsLong) PInvoke()
{
return GetVersion_PInvoke();
}
The generated code for "GetVersion_PInvoke" is:
[MethodImpl(MethodImplOptions.ForwardRef), SuppressUnmanagedCodeSecurity,
DllImport("kernel32.dll", EntryPoint="GetVersion")]
private static extern uint modopt(IsLong) GetVersion_PInvoke();



Of course, I had not verified what the JIT-compiler is doing with this
attributes... but I assume that IJW is at least as time consimung as the
DLLImport-way.

Remember Rico Mariani's first rule of performance? "Profile first." You
have absolutely no evidence to back your claim, while I've read dozens of
blog posts by the MS C++ compiler team that discuss the ways C++ interop
(IJW) is faster, including some who profiled.
 
Hi Ben!

Thanks for this link! Didn't know this.
Remember Rico Mariani's first rule of performance? "Profile first." You
have absolutely no evidence to back your claim, while I've read dozens of
blog posts by the MS C++ compiler team that discuss the ways C++ interop
(IJW) is faster, including some who profiled.

Sorry; you are right. As I said, I did not profile the
marshaling/JIT-issues... sorry again.

Thanks for your enlightenment!

--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/
 
Back
Top