-
Notifications
You must be signed in to change notification settings - Fork 112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Question] - Pass struct/slice of structs from C# <---> Go #28
Comments
@aleqsss The simplest way to pass an object from C# to Go and back is to serialize the object as a JSON byte array. You can use the same extension methods as for byte[]. In C#, you can use the built-in using System.Text.Json;
public struct Person
{
public string Name { get; set; }
public string[] Hobbies { get; set; }
public long[] FavouriteNumbers { get; set; }
public long Age { get; set; }
public bool Single { get; set; }
public Person(string Name, string[] Hobbies, long[] FavouriteNumbers, long Age, bool Single)
{
this.Name = Name;
this.Hobbies = Hobbies;
this.FavouriteNumbers = FavouriteNumbers;
this.Age = Age;
this.Single = Single;
}
} Note that C# P/Invoke Signature: [DllImport(libName, CallingConvention = CallingConvention.Cdecl)]
public static extern GoSlice Struct(GoSlice person); Now create an object and serialize it. Here's an example: // Create a new person in C#
Person person = new Person("Thomas", new string[] { "Golfing", "Horse Riding" }, new long[] { 1, 3, 7 }, 28, true);
// Serialize person object to JSON byte array
byte[] personData = JsonSerializer.SerializeToUtf8Bytes(person);
GoSlice returnedPersonSlice = Struct(personData.ToGoSlice());
// Returned structure
Person personReturned = JsonSerializer.Deserialize<Person>(returnedPersonSlice.ToByteArray());
Console.WriteLine(personReturned.Name);
Console.WriteLine(string.Join(", ", personReturned.Hobbies));
Console.WriteLine(personReturned.Age); In the above code, we first create a new Person object with some sample data. We then use the Next, we pass the JSON byte array to the Struct function. The Struct function returns a GoSlice, which we store in the returnedPersonSlice variable. Finally, we use the Now, in Go code, you need to add import "encoding/json"
type Person struct {
Name string
Hobbies []string
FavouriteNumbers []int
Age int
Single bool
}
//export Struct
func Struct(person []byte) (unsafe.Pointer, int, int) {
// Get person from C#
var personStruct Person
json.Unmarshal(person, &personStruct)
fmt.Println(personStruct.Name, personStruct.Hobbies, personStruct.FavouriteNumbers, personStruct.Age, personStruct.Single)
// Create a Person struct instance
newPerson := Person{
Name: "John",
Hobbies: []string{"Golf", "Hiking", "Outdoors"},
FavouriteNumbers: []int{7, 13, 42},
Age: 21,
Single: false,
}
// Convert the newPerson object to JSON byte slice
data, _ := json.Marshal(newPerson)
size := len(data)
// allocate a C buffer to hold the data
buffer := C.CBytes(data)
// return the C buffer, its size and capacity
return buffer, size, size
} In the above code, the Next, we create a new Person object The result after executing command
If you want to pass an array of Person objects from C# to Go and back, it will be very similar to passing a single object. Here's an example for C# code: // Create an array of people in C#
Person[] people = new Person[]{
new Person("Thomas", new string[] { "Golfing", "Horse Riding" }, new long[] { 1, 3, 7 }, 28, true),
new Person("James", new string[] { "Reading", "Yoga" }, new long[] { 2, 4 }, 32, true),
new Person("Robert", new string[] { "Painting", "Photography" }, new long[] { 4, 5, 17 }, 23, false)
};
// Serialize people array to JSON byte array
byte[] peopleData = JsonSerializer.SerializeToUtf8Bytes(people);
GoSlice returnedPeopleSlice = StructSlice(peopleData.ToGoSlice());
// Returned people array
Person[] peopleReturned = JsonSerializer.Deserialize<Person[]>(returnedPeopleSlice.ToByteArray()) ?? Array.Empty<Person>();
foreach (Person person in peopleReturned)
{
Console.WriteLine(person.Name);
Console.WriteLine(string.Join(", ", person.Hobbies));
Console.WriteLine(person.Age);
} In the above code, we create an array of Person objects and serialize it to JSON byte array. Then we call function C# P/Invoke Signature: [DllImport(libName, CallingConvention = CallingConvention.Cdecl)]
public static extern GoSlice StructSlice(GoSlice people); In Go code, we create an exported function //export StructSlice
func StructSlice(people []byte) (unsafe.Pointer, int, int) {
// Get people from C#
var peopleSlice []Person
json.Unmarshal(people, &peopleSlice)
for _, person := range peopleSlice {
fmt.Println(person.Name, person.Hobbies, person.FavouriteNumbers, person.Age, person.Single)
}
// Create a Person struct instance
newPeople := []Person{
{
Name: "John",
Hobbies: []string{"Golf", "Hiking", "Outdoors"},
FavouriteNumbers: []int{7, 13, 42},
Age: 21,
Single: false,
},
{
Name: "Jennifer",
Hobbies: []string{"Swimming", "Outdoors"},
FavouriteNumbers: []int{1, 9},
Age: 30,
Single: true,
},
}
// Convert the newPeople slice to JSON byte slice
data, _ := json.Marshal(newPeople)
size := len(data)
// allocate a C buffer to hold the data
buffer := C.CBytes(data)
// return the C buffer, its size and capacity
return buffer, size, size
} As always, don't forget to call the The result after executing command
|
This is awesome! I'll comment here once I've tried it out. 👏 I'll also send you one more donation for these educating replies. I trust that the other found it's way to you? |
Hello once again @Digital-512
As mentioned in #27, I'm now seeking assistance for the task of passing a struct and also a slice of structs, from C# to a CGO exported function, and returning a struct and also a slice of structs, from a CGO exported function to the calling C# code.
Consider the following example struct in Go:
Which is then called as a single struct or a slice of structs:
Building on top of your other provided snippets, what would be a suitable way of doing this?
How would I go on about passing both a single struct but also a slice of structs from C# to a CGO exported Go function, and also return them? Such as these examples:
Just get back if you need me to clearify anything, as I do see that I can get quite confusing in my examples and attempts to explain, because of my lack of knowledge in the topics.
The text was updated successfully, but these errors were encountered: