marshal string data from unmanaged to managed

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I found a lot of information on passing data from C# to a C++ dll
What I cannot find is a way to return C++ structs of TCHAR string data back
to the C# managed code!

typedef struct // C++ data that needs to be returned to the caller (C#)
{
short snOperParams;
TCHAR szNFPath[PATH_SIZE];
TCHAR szSSFile[PATH_SIZE];
TCHAR szExeFile[PATH_SIZE];
TCHAR szOpLibIFile[PATH_SIZE];
TCHAR szOpLibMFile[PATH_SIZE];
TCHAR szDefaultIFile[PATH_SIZE];
TCHAR szDefaultMFile[PATH_SIZE];
TCHAR szMiscFile[PATH_SIZE];
TCHAR szAuxFile[PATH_SIZE];
TCHAR szSuffix[PATH_SIZE];
} files;
 
zDog,

You would want to do this:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public struct <StructureName>
{
public short snOperParams;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szNFPath;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szSSFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szExeFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szOpLibIFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szOpLibMFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szDefaultIFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szDefaultMFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szMiscFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szAuxFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szSuffix;
}

Just make sure that you define <StructureName> and define a constant for
PATH_SIZE.

Hope this helps.
 
Nicholas,

Thanks for the response!
That is what I was trying without success.

If I initialize the strings, that data gets over to the unmanaged code side
OK.
But the caller gets nothing but garbage back! ;(
(I really do not need to pass anything to the callee, I just need to
retrieve loads of data back to the caller)


Sample -->

/// *** C++ code -->>

//-----------------------------------------------------------------------------------
// Retrieve the File Path Settings (from unmanaged DLL
//-----------------------------------------------------------------------------------
extern "C" __declspec(dllexport) bool get_file_paths (files_path_struct
&file_paths)
{

// 'files_path_struct' is the matching (local) C++ struct of TCHAR
<name>[260]
// Need to copy those strings into the (file_paths) struct/class passed in
from C#

strncpy(file_paths.szNFPath, the_file_paths.szNFPath, 260);
strncpy(file_paths.szSSPath, the_file_paths.szSSPath, 260);

return true;
}


/// *** C# code -->>

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public class file_paths
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)]
public string szNFPath;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)]
public string szSSFile;
} fpaths;


[DllImport("x.dll")]
public static extern bool get_file_paths(
[In, Out, MarshalAs(UnmanagedType.LPStruct)]
file_paths test_file_paths
);

------
zDog
------


Nicholas Paldino said:
zDog,

You would want to do this:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public struct <StructureName>
{
public short snOperParams;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szNFPath;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szSSFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szExeFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szOpLibIFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szOpLibMFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szDefaultIFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szDefaultMFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szMiscFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szAuxFile;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PATH_SIZE)]
public string szSuffix;
}

Just make sure that you define <StructureName> and define a constant for
PATH_SIZE.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


zDog said:
I found a lot of information on passing data from C# to a C++ dll
What I cannot find is a way to return C++ structs of TCHAR string data
back
to the C# managed code!

typedef struct // C++ data that needs to be returned to the caller (C#)
{
short snOperParams;
TCHAR szNFPath[PATH_SIZE];
TCHAR szSSFile[PATH_SIZE];
TCHAR szExeFile[PATH_SIZE];
TCHAR szOpLibIFile[PATH_SIZE];
TCHAR szOpLibMFile[PATH_SIZE];
TCHAR szDefaultIFile[PATH_SIZE];
TCHAR szDefaultMFile[PATH_SIZE];
TCHAR szMiscFile[PATH_SIZE];
TCHAR szAuxFile[PATH_SIZE];
TCHAR szSuffix[PATH_SIZE];
} files;
 
Back
Top