65.9K
CodeProject is changing. Read more.
Home

char, sbyte, byte and uint with arrays and pointers

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.67/5 (3 votes)

Jan 18, 2024

CPOL

5 min read

viewsIcon

13423

There are new convertions for C#

Introduction

I would like to show about modern convertion functions for C# and they can work everything if you use SDL2 ( DeafMan1983.Interop.SDL2 ) / SDL3 ( DeafMan1983.Interop.SDL3, WIP ) or GTK4/5 and pure code with Qt6 ( without Qt6 frameworks, only hard-coded sources with WinAPI and X11, xcb and other windowing system runtimes for Linux, macOS and Android, also iOS ( I am not sure ))

Background

Since I am supervising about NativeAot used dotnet apps like AppWithPlugins and PaintNet ( WIP ) and I have a lot of works with modern convertion functions like you have not problem with WinAPI without fixed-statements.

Using the Code

**NEW**
Explanations of char[], char*, char**, char*[] and char[][]:
char[] StringToCharArray(string intput) It works like string.ToCharArray();
string CharArrayToString(char[] ary) It likes new string(char[] ary);
char* StringToCharPointer(string intput) It is really special pointer for char* with TerraFX.Interop.Windows unlike in C/C++ example wchar* or TChar*
string CharPointerToString(char* ptr) is a back converter unlike in C/C++ std::string
char** StringArrayToCharDoublePointer(string[] inputs) like in C/C++ wchar** argv
string[] CharDoublePointerToStringArray(char** dblPtr) like in C/C++ wchar** argv
char*[] CharDoublePointerToCharPointerArray(char** dblPtr) convert to char*[]
char** CharPointerArrayToCharDoublePointer(char*[] ptrAry) convert to char**
char[][] CharPointerArrayToCharDoubleArray(char*[] ptrAry) is an advanced array length of char[] and can work everything like in any C/C++. Because I have seen about char[][] example int main(int argc, char** argv) { ... } like Quake 2 or Half-Life have to use char[][] from CommandLine or any functions but I will look for more functions.
char*[] CharDoubleArrayToCharPointerArray(char[][] dblAry) like I explained with char[][] .....
int CharPointerLength(char* ptr) it is new function for char*. Don't need to worry about complication/problem! It works like in char[].
Example:

string str_1 = "Hello World!";
char* charPtr_1 = StringToCharPointer(str_1);
Console.WriteLine($"Result: Importing string from char {CharPointerToString(charPtr_1)}");
Console.WriteLine($"Length of char*: {CharPointerLength(charPtr_1)}");

Result:

Result: Importing string from char Hello World!
Length of char*: 12

int CharDoublePointerLength(char** dblPtr) is not normal length, just is array length like char[][].
Please do not forget for string[] to char** has problem because I have tried to fix. It seems wrong cause string[] doesn't have correct array size like 4 = size of array but it need to fix:
[ HELLO ][ HELLO ][ HELLO ]/[ HELLO ] <- It means wrong length.
That is why we need to resolve if you add string.Empty or null as last length then it will able working fine. Example:

string[] strings = { "Haha ", "Hehe ", "Hihi ", "Hoho ", "Huhu", string.Empty }; // <- Fix if you don't see last item of array.
char** charDblPtr_1 = StringArrayToCharDoublePointer(strings);
for(int i = 0; i < strings.Length - 1; i++) // Need to -1
{
    charDblPtr_1[i] = StringToCharPointer(strings[i]);
    Console.WriteLine($"{strings[i]}");
}
charDblPtr_1[strings.Length - 1] = null; // <- Need fix null

int arrayLength = CharDoublePointerLength(charDblPtr_1);
Console.WriteLine($"Length of char**: {arrayLength} ");

Result:

Haha
Hehe
Hihi
Hoho
Huhu
Length of char**: 5

Please be careful if you use char*[] or char** to string[] is ok!
Example with CharPointerArrayToCharDoublePointer()

char*[] charPtrArrays = new char*[]
{
    StringToCharPointer("Bill Gates"), // USA, Ex Microsoft boss
    StringToCharPointer("Jeff Bezos"), // USA Amazon boss
    StringToCharPointer("Tim Cook"), // USA Apple boss
    StringToCharPointer("Thomas Mueller"), // Germany /[ mýler }/, soccer of Bayern Munich
    StringToCharPointer("Nils Petersen"), // Germany, ex soccer of SC Freiburg
    StringToCharPointer("Christian Streich"), // Germany, ex coacher of SC Freiburg
    StringToCharPointer("Juegen Klopp"), // Germany /[ jýken ]/, ex chacher of Liverpool FC
    StringToCharPointer("Olaf Scholz"), // Germany, prime minister of Germany
    StringToCharPointer("Angela Merkel"), // Germany, ex prime minister of Germany
    StringToCharPointer("Jericho Rosales"), // Philippines, player for television
};
char** charDblPtr_2 = CharPointerArrayToCharDoublePointer(charPtrArrays);
for (int i = 0; i < charPtrArrays.Length; i++)
{
    Console.WriteLine($"{i + 1} Name: {CharPointerToString(charDblPtr_2[i])}");
}

int arrayLength_2 = CharDoublePointerLength(charDblPtr_2);
Console.WriteLine("Array Length of char*[] {0} ", arrayLength_2); 

Result:

1 Name: Bill Gates
2 Name: Jeff Bezos
3 Name: Tim Cook
4 Name: Thomas Mueller
5 Name: Nils Petersen
6 Name: Christian Streich
7 Name: Juegen Klopp
8 Name: Olaf Scholz
9 Name: Angela Merkel
10 Name: Jericho Rosales
Array Length of char*[] 10 

And other example with CharDoubleArrayToCharPointerArray()

char[][] charArrayArray = new char[][]
{
    new char[] { 'H', 'e', 'l', 'l', 'o' },
    new char[] { 'W', 'o', 'r', 'l', 'd' },
    StringToCharArray("and"),
    StringToCharArray("Mars's World")
};

char*[] chardblArray = CharDoubleArrayToCharPointerArray(charArrayArray);
foreach (var charAry in charArrayArray)
{
    Console.WriteLine($"CharArray: {CharArrayToString(charAry)}");
}

char[][] chardblArray_2 = CharPointerArrayToCharDoubleArray(chardblArray);
for (int i = 0; i < chardblArray_2.Length;i++)
{
    Console.WriteLine($"{i + 1} CharArray: {CharArrayToString(chardblArray_2[i])}");
}

int array_length = CharDoublePointerLength( // <- Length of char double pointer
                        CharPointerArrayToCharDoublePointer( // <- trying char** from char*[]
                            CharDoubleArrayToCharPointerArray(chardblArray_2) // <- trying char*[] from char[][]
                        )
                    );
Console.WriteLine($"Array Length of char[][] is {array_length}"); 

Result:

CharArray: Hello
CharArray: World
CharArray: and
CharArray: Mars's World
1 CharArray: Hello
2 CharArray: World
3 CharArray: and
4 CharArray: Mars's World
Array Length of char[][] is 4 

That is all with char[], char*, char**, char*[] and char[][] and more ...
If you are excited to use with TerraFX.Interop.Windows then you will enjoy your new functions with charX/charXX and length of char* and char** and enjoy your development....


sbyte* <-> string and string <-> sbyte*

Example for SDL2 Wrapper (DeafMan1983.Interop.SDL2):

For string to sbyte* and sbyte* from string):

// Example for title in SDL_CreateWindow()
sbyte* title = SBytePointerFromString("HelloSDL");
...
SDL_Window* window = SDL_CreateWindow(title, ... );

Or sbyte* to string (string from sbyte*).

// Example for printf()

[DllImport("c")]
private static extern int printf(sbyte* fmt);
public static int Printf(sbyte* fmt, params object[] args)
{
    string result = StringFromSBytePointer(fmt);
    if (result == null)
        return 1;
    return printf(SBytePointerFromString(string.Format(result, args));
}

Two nice ways for sbyte* and string, you can use like this.

And nice example with Gtk3/Gtk4:

string[] to sbyte** (sbyte** from string[])

static int Main(string[] args)
{
    GtkApplication* app = gtk_application_new(SBytePointerFromString("org.gtk.example"), 
                          GApplicationFlags.G_APPLICATION_FLAGS_NONE);
    g_signal_connect(app, ACTIVATE, G_CALLBACK
                    ((delegate* <gtkapplication*, void*, void>)&Activate), null);

    int argc = args.Length;
    sbyte** argv = SByteDoublePointersFromStringArray(args);
    int status = g_application_run(G_APPLICATION(app), argc, argv);

    g_object_unref(app);
    return status;
}

That is tricky and you can develop with C/C++ like main function with int and char* or char*[], etc. into C#.

sbyte** to string[] (string[] from sbyte**)

No code available. You know it just works like arguments/parameters from shared library example: Half-Life Sharp (still work in process).

Points of Interest

I find it very funny because ClangSharpPInvokeGenerator made const char* or char** into sbyte* or sbyte** because C/C++ <-> C# are not the same but for WinAPI is very sensitive because WinAPI doesn't support for sbyte* / sbyte** just uses char* / char** like in C/C++.

I expect that wchat* and  TChat* are not same to normal chat* because wchat means Windows-Charecter and has only 2 bytes.

Since it is sensitive, I need to fix for UTF8 or ANSI format in char*/char**.

UPDATE: char* to string, string to char* and length of char* released

WARNING: Package will move to "DeafMan198.Utilities"

UtilitiesForUTF16 -> char* to string, string to char* and length of char* ( char** to string[] and string[] to char** and more will come see in Using in code )
UtilitiesForSByte -> sbyte* to string and string to sbyte* ( length of sbyte comes soon )
UtilitiesForByte -> byte* to string and string to byte* ( length of byte comes soon )

I have reworked hard with char* (UTF16) to string (UTF8)

Example: For WinAPI ( TerraFX.Interop.Windows )

How do I get successful with WinAPI under C#.

Example:

...
    static string DesktopAppStr = "DesktopApp";
    static string TitleStr = "Windows Desktop Guided Tour Application";

...

        HWND hWnd = CreateWindowEx(
            WS_EX_OVERLAPPEDWINDOW,
            StringToCharPointer(DesktopAppStr),
            StringToCharPointer(TitleStr),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT,
            500, 100,
            HWND.NULL,
            HMENU.NULL,
            hInstance,
            null
        );

... 

That is all for WinAPI. I am very excited to see if Chinese Language won't show up. Yay!

Enjoy your reading if I release package for char* and string and length of char*.

For byte* <-> string:

byte* StringToBytePointer(string input)
string BytePointerToString(byte* ptr)
int BytePointerLength(byte* ptr)
byte** StringArrayToByteDoublePointer(string[] input)
string[] ByteDoublePointerToStringArray(byte** ptrArray)
Int ByteDoublePointerLength(byte** ptrArray)

sbyte** <-> string:

sbyte* StringToSBytePointer(string input)
string SBytePointerToString(sbyte* ptr)
int SBytePointerLength(sbyte* ptr)
sbyte** StringArrayToSByteDoublePointer(string[] input)
string[] SByteDoublePointerToStringArray(sbyte** ptrArray)
Int SByteDoublePointerLength(sbyte** ptrArray)

char* <-> string:

char* StringToCharPointer(string input)
string CharPointerToString(char* ptr)
int CharPointerLength(char* ptr)
char** StringArrayToCharDoublePointer(string[] input)
string[] CharDoublePointerToStringArray(char** ptrArray) 
Int CharDoublePointerLength(char** ptrArray)

History

I started with SDL2-CS by Ethan Lee. But his SDL2-CS cannot use NativeAot. That is why I reworked into DeafMan1983.Interop.SDL2 with full pointers like in C/C++ because it works fine for NativeAot support. And new version comes with char* and more new features. It works as well with TerraFX.Interop.Windows.  

Add missed explanation about functions.

If you would like to spend me because I have a lot of works with trying fixes with string[] and char** that's way. See information !

Sorry no PayPal/Skrill:
Only TRX, MATIC or LTC under crypto wallet cause I have to earn more money.
Please notify me! Okay!

Nuget Gallery

It will come soon. ( I am working currently. Sorry for hesitation! )

Check out Nuget Package

dotnet add package DeafMan1983.Utilities

It uses sbyte*<->string ,sbyte**<->string[], and new char´*<->string and more new ...

If you want to check my Nuget packages, you can visit my packages.

Have fun and happy coding!