C# convert string Unicode to byte Ansi - c#

google didnt help me such as i wanted so im writing post here.
i have Unicode string in C# and C function (in dll) which want the char(ANSI)*.
i try to do
string tmp = "ala ma kota";
unsafe
{
fixed (byte* data = &tmp.ToCharArray()[0])
{
some_function(data);
}
}
but i cannot convert directly without encoding. I try to use Encode class but without any effects. I know that, the some_function needs to be called with char pointer. Where it points to array of byte.

You don't need to do this explicitly yourself.
Instead, declare the C method using P/Invoke to accept a parameter of type string.
Then add to the P/Invoke declaration:
[DllImport("YourDllName.dll", CharSet=CharSet.Ansi)]
The marshaller will then convert the string to ANSI for you.
Note that I'm assuming that the string is being passed TO the called function, so the parameter is NOT a pointer being used to return a new string FROM the called function.
See here for more details: http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.charset.aspx
In fact, the default is CharSet.Ansi so you might only need to declare the parameter as string instead of byte* (or whatever you are using just now).

You should use the System.Text namespace:
string tmp = "ala ma kota";
unsafe
{
fixed (byte* data = &System.Text.Encoding.ASCII.GetBytes(tmp)[0])
{
some_function(data);
}
}

Related

Function with multiple return parameter

I am new to C#. For a motor driver that we use, I want to see its current and there is a BOOL function in motor driver's guide. But I have no idea how I can use it.
VCS_GetCurrentIsAveraged(KeyHandle,NodeId, short* pCurrentIsAveraged,
pErrorCode)
for this function KeyHandle and NodeId are parameters and pCurrentIsAveraged and pErrorCode are return parameters.
I have all parameters already in my code except pCurrentIsAveraged, which is what I want to see. So how can I get this value as a return.
//Initialize
short* pCurrentIsAveraged;
double current;
current=VCS_GetCurrentIsAveraged(KeyHandle,NodeId,pCurrentIsAveraged,
pErrorCode)
Would this work, I want to get current but what should I enter for pCurrentIsAveraged value as return parameter?
Thanks.
Using the function signature VCS_GetCurrentIsAveraged(KeyHandle,NodeId, short* pCurrentIsAveraged, pErrorCode) requires you to use unsafe code, which, if you are new to C#, you should avoid. That looks like a p/invoke wrapper around a C-style API.
As it stands, you would need to call it like this (from an unsafe block) (fixing may not be needed if currentIsAveraged happens to be allocated on the stack):
short currentIsAveraged = 0;
double current;
fixed (short* pCurrentIsAveraged = &currentIsAveraged) {
current = VCS_GetCurrentIsAveraged(KeyHandle,NodeId,pCurrentIsAveraged, pErrorCode);
}
bool isCurrentAveraged = (currentIsAveraged != 0);
If you have control of the p/invoke definition of VCS_GetCurrentIsAveraged, you could change that signature to use an ref short pCurrentIsAveraged rather than short* pCurrentIsAveraged. This would let you use that method like this (without the need for unsafe code):
short currentIsAveraged = 0;
double current;
current = VCS_GetCurrentIsAveraged(KeyHandle,NodeId,ref currentIsAveraged, pErrorCode);
bool isCurrentAveraged = (currentIsAveraged != 0);
You can optimize the p/invoke signature further by using [Out] attribute on that value to tell the marshaller to skip a probably unneeded copy, and you could also convice the compiler to treat it as a bool directly rather than going back and forth with a short, but that's all advanced stuff. Check out the System.Runtime.InteropServices namespace if you are interested in that.

Converting from string to char* only copies the first character

I have looked at most of the string to char* conversion SO answers, but it is not working for me. Here is my code:
public static void Main() {
string name = "ELEM";
unsafe{
fixed(char* name_ptr = name) {
Console.WriteLine(name_ptr->ToString());
}
}
}
// Output: E
I need to do this since I have to pass a char* to my C++ custom DLL. Why would it only copy the first character only, and how can I properly convert string to a char*?
You get the first character only, because name_ptr is nothing but a reference to a single character and when you call name_ptr->ToString() you actually call char.ToString().
You should use a StringBuilder instead to pass a string to a C/C++ DLL. See this question.

Passing a byte array from C# into C++ com object with C++ filling array

I need to pass a byte array into a C++ com object from C#. C++ will then fill the buffer for C# to read.
c++ function definition
STDMETHODIMP CSampleGrabber::GetBuffer(byte* bd)
{
int p=0;
while (p< nBufSize) {
bd[p]=pLocalBuf[p];
p++;
}
c# code :
byte[] byTemp = new byte[nBufSize];
igb.GetBuffer(ref byTemp);
This crashes the program with no exception. Please can someone help. Thanks
SOLVED:
with
byte[] byTemp = new byte[nBufSize];
GCHandle h = GCHandle.Alloc(byTemp, GCHandleType.Pinned);
igb.GetBuffer(h.AddrOfPinnedObject());
Thanks
The parameter should not be declared as ref. You want something like:
uint GetBuffer(byte[] bd);
If you include the ref you are passing a pointer to the array, when you just want the array. (And by array, I mean pointer to the first element.)
I know this is an old question, but Google brought me here so it might bring someone else.
If you're using P/Invoke to call:
... GetBuffer(byte* bd)
it should look something along the lines of
[DllImport("MyDll.dll")]
... GetBuffer(ref byte bd);
And a buffer array in c# should be passed in like this:
var arr = new byte[Length];
GetBuffer(ref arr[0]);
This also works with char*, as you can just pass in the same byte array reference and then use string s = Encoding.<encoding>.GetString(arr);

Generating a struct at run-time based on data types defined in a string

How can I generate a struct at run-time from a sequence of types defined in a string?
I have a header that e.g. contains "float, float, byte[255]".
I have binary data that follows this header and keeps the data in sequence.
I don't know the data type until I read the header at run-time, and I would like to generate a struct that I can used to Marshal the binary data into an array of structs.
Any ideas?
Obviously you know what the requirements of your application are, but as lejon stated the problem is how to access the struct once you create it. In c# you will have to jump through hoops, as opposed to vb where you don't need to explicitly declare types.
I can think of several ways to accomplish what you want. You could use CodeDom to generate your code, see this http://www.15seconds.com/issue/020917.htm
Personally for a simply struct, I would constuct the code mandually
string szCode =#"using System;
using System.Windows.Forms;
namespace RunTimeCompile
{
[StructLayoutAttribute(LayoutKind.Sequential)]
public string MyStruct
{"
Then for each data type in your head file append the member to the szCode String. (You'll need to build a basic function to parse your types this):
szCode += "float Field1;\n";
szCode += "float Field2;\n";
szCode += "byte[255] Field3;\n";
and close off your code...
szeCode+=";\n;\n";
now that you have the source code use CodeDom to compile it.
oCodeDomProvider = CodeDomProvider.CreateProvider("CSharp");
// Add what referenced assemblies
CompilerParameters oCompilerParameters = new CompilerParameters();
oCompilerParameters.ReferencedAssemblies.Add("system.dll");
// set the compiler to create a DLL
oCompilerParameters.GenerateExecutable = false;
// set the dll to be created in memory and not on the hard drive
oCompilerParameters.GenerateInMemory = true;
oCompilerResults =
oCodeDomProvider.CompileAssemblyFromSource(oCompilerParameters, szCode);
Note: You could also compile from a file as opposed to in memory source code using CompileAssemblyFromFile
Now before continuing check there are no compilation errors
if (oCompilerResults.Errors.Count!=0) return; // add you own error handling
now you can retrieve an instance of the dynamically generated struct like this
oAssembly = oCompilerResults.CompiledAssembly;
oObject = oAssembly.CreateInstance("RunTimeCompile.MyStruct");
oType = oObject.GetType();
Now you can read all of the rows of your binary file and Marshal them into an array of MyStruct[] using Marshal or any other method your would like to serialize the binary data (binary serializer perhaps).
For example using Runtime.Interop.Marshal you could do something like this (you'll need to fiddle with this a bit, specifically you can't declare MyStruct[] in your code so you need to do something like oObjectArray = oAssembly.CreateInstance("RunTimeCompile.MyStruct[]") to declare the destValues result array):
byte[] sourceData = ReadSourceData(); // TODO: generate method to load your BLOB
MyStruct[] destValues = new MyStruct[Marshal.SizeOf(oType) + 1]
int arrayIndex = 0;
GCHandle handle = GCHandle.Alloc(sourceData, GCHandleType.Pinned);
try
{
IntPtr buffer = handle.AddrOfPinnedObject();
buffer = (IntPtr)(buffer.ToInt32() +
(arrayIndex*Marshal.SizeOf(typeof(MyStruct))));
destStruct = (MyStruct)Marshal.PtrToStructure(buffer, typeof(MyStruct));
}
finally
{
handle.Free();
}
return MyStruct;
Now you have your array of struct.
The problem is, once you've defined your struct, how would you access it? You can't reference it statically, as the type is runtime only. You would either have to use reflection, delegates, or dynamic. Is there a better way of doing what you want (say, a single class that takes the byte array and interprets it as you need) rather than generating a struct at runtime?

Marshalling a struct containing c-strings

I have a C++ struct
struct UnmanagedStruct
{
char* s;
};
and a C# struct
struct ManagedStruct {
string s;
}
How can I marshal the UnmanagedStruct? Do I need to use a StringBuilder?
the C++ library exposes UnmanagedStruct getStruct();
Edit & Correction: For return values of p/invoke calls, the "normal" method doesn't work. I was so used to the normal, ref, and out behaviors related to method parameters that I assumed return values would work in a similar fashion. Here is the link for a solution to the return value problem:
PInvoke error when marshalling struct with a string in it
You only need to use a StringBuilder if you are passing the struct to the C++ method as a byref parameter and the string is a buffer that the method will alter. For a return value, you just need to specify the type of string, which in this case is:
struct ManagedStruct
{
[MarshalAs(UnmanagedType.Lpstr)]
string s;
}
Rememer to add a property to expose the string, since s is private here (which is OK, fields should be private).

Categories

Resources