예제 #1
0
파일: Program.cs 프로젝트: bonomali/Ibasa
        public void CompileProgram(Device[] devices, string options, Tuple <Program, string>[] headers, Action <Program, object> notify, object user_data)
        {
            unsafe
            {
                var devices_length = devices == null ? 0 : devices.Length;
                var device_list    = stackalloc IntPtr[devices_length];

                for (int i = 0; i < devices_length; ++i)
                {
                    device_list[i] = devices[i].Handle;
                }

                device_list = devices_length == 0 ? null : device_list;

                int   length = options == null ? 0 : Encoding.ASCII.GetByteCount(options);
                byte *chars  = stackalloc byte[length + 1];

                if (options != null)
                {
                    fixed(char *options_ptr = options)
                    {
                        Encoding.ASCII.GetBytes(options_ptr, options.Length, chars, length);
                    }

                    chars[length] = 0; //null terminator
                }
                else
                {
                    chars = null;
                }

                var num_headers = headers == null ? 0 : headers.Length;

                IntPtr *input_headers        = stackalloc IntPtr[num_headers];
                byte ** header_include_names = stackalloc byte *[num_headers];

                for (int i = 0; i < num_headers; ++i)
                {
                    input_headers[i] = headers[i].Item1.Handle;

                    var   name          = headers[i].Item2;
                    var   header_length = Encoding.ASCII.GetByteCount(name);
                    byte *header_chars  = (byte *)Marshal.AllocHGlobal(length + 1).ToPointer();
                    fixed(char *name_ptr = name)
                    {
                        Encoding.ASCII.GetBytes(name_ptr, name.Length, header_chars, header_length);
                    }

                    header_chars[header_length] = 0; //null terminator
                    header_include_names[i]     = header_chars;
                }

                if (headers == null)
                {
                    input_headers        = null;
                    header_include_names = null;
                }

                var function_ptr = IntPtr.Zero;
                var data_ptr     = new GCHandle();

                if (notify != null)
                {
                    var data = Tuple.Create(notify, user_data);
                    data_ptr = GCHandle.Alloc(data);

                    function_ptr = Marshal.GetFunctionPointerForDelegate(new CallbackDelegate(Callback));
                }

                try
                {
                    ClHelper.GetError(Cl.CompileProgram(Handle, (uint)devices_length, device_list, chars,
                                                        (uint)num_headers, input_headers, header_include_names,
                                                        function_ptr, GCHandle.ToIntPtr(data_ptr).ToPointer()));
                }
                catch (Exception)
                {
                    data_ptr.Free();
                    throw;
                }
                finally
                {
                    for (int i = 0; i < num_headers; ++i)
                    {
                        Marshal.FreeHGlobal(new IntPtr(header_include_names[i]));
                    }
                }
            }
        }