Array of structures within a structure

Apr 21, 2016 at 8:26 PM
I am using CUDAfy .NET and want to pass a struct array within a struct to the device.

I have declared them in c# as shown below:
[Cudafy(eCudafyType.Struct)]
[StructLayout(LayoutKind.Sequential)]
public struct A
{
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType= UnmanagedType.Struct, SizeConst = 3)]
    public B[] ba;
}

[Cudafy(eCudafyType.Struct)]
[StructLayout(LayoutKind.Sequential)]
public struct B
{
    public byte id;
 }
This results in the following source code for the GPU:
struct B
{
        unsigned char id;
};


struct A
{
        B ba [3]; 
        int baLen0;
 };
And I get this compilation error from an attempt to convert it to OpenCL code:
Compilation error: <kernel>:20:2: error: must use 'struct' tag to refer to type 'B'
    B ba [3]; int baLen0;
    ^
    struct
I realize this could be an issue between the marshalling and how CUDAfy .NET handles structures, but is there any way I could possibly change this to work, or can CUDAfy .NET be changed include the struct keyword in the other structure?

Thanks in advance
Apr 22, 2016 at 1:50 PM
AFAIK that particular problem was never fixed during the cudafy's opencl adaptation.
Apr 22, 2016 at 6:51 PM
I've stepped through the source and at one point I have seen A being converted with ba as a field with B as the type. It's not straight forward enough for me to edit it without digging further, and even then it's possible that Microsoft libraries are doing the heavy lifting and CUDAfy .NET has nothing to do with it.

I could simply wait till the code is in a string format and use some regex to include the struct keyword.
Apr 23, 2016 at 4:15 AM
I manadll

to alter the CUDAfy .NET library in the CudafyTranslator. After the structs were in a memory stream I added:
        StreamReader sr = new StreamReader(structs);
        String sStructs = sr.ReadToEnd();
        String sNewStructs;
        foreach(string structName in cm.Types.Values.Select(t => t.Name))
        {
            while (true)
            {
                string regex = @"^(?<start>\s+)" + structName + @"(?<end>\s+\S+( \[\d+\])?;)";
                sNewStructs = Regex.Replace(sStructs, regex, @"${start}struct " + structName + "${end}", RegexOptions.Multiline);
                if (sNewStructs.Length == sStructs.Length)
                {
                    break;
                } else
                {
                    sStructs = sNewStructs;
                }
            }
        }
        structs = new MemoryStream();
        StreamWriter sw = new StreamWriter(structs);
        sw.WriteLine(sStructs);
        sw.Flush();
It's a bit sloppy but it works, I then rebuilt CUDAfy .NET and ilmerged it and replaced my dll

Basically for each type it will try to find a field of that type and add struct in front of it.
Apr 23, 2016 at 3:08 PM
It hurts my eyes, but I admit it may help me in the future, so thanks for sharing that with the rest of us ;)
Apr 25, 2016 at 1:54 AM
No worries, if you can find a clearer implementation I'm all for it.
Apr 25, 2016 at 1:32 PM
I meant it hurts my eyes seeing the code being altered post-generation through regexs; it was not a remark on the quality of the code itself :)