Объявите тип nativeptr <unit> - PullRequest
       22

Объявите тип nativeptr <unit>

2 голосов
/ 28 декабря 2010

Я хотел бы знать, возможно ли в F # объявить тип:

nativeptr<unit>

Это кажется невозможным (компилятор жалуется на "Универсальная конструкция требует, чтобы тип 'unit' был неуправляемым типом" ). Есть ли обходной путь, который я мог бы использовать?

Конечная цель - объявить мой собственный blitDelegate для предоставления кода операции Cpblk некоторым моим F # -кодам.

Спасибо.

Изменить:

Вот что я попробовал, основываясь на ответе kvb:

type blitDelegate<'T when 'T : unmanaged> = delegate of nativeptr<'T> * nativeptr<'T> * uint32 -> unit

let createBlitDelegate<'T when 'T : unmanaged>() =
    let dm = new DynamicMethod("blit",
                               typeof<System.Void>,
                               [| typeof<nativeptr<'T>>; typeof<nativeptr<'T>>; typeof<uint32> |])
    let ilGenerator = dm.GetILGenerator()
    ilGenerator.Emit(OpCodes.Ldarg_0)
    ilGenerator.Emit(OpCodes.Ldarg_1)
    ilGenerator.Emit(OpCodes.Ldarg_2)
    ilGenerator.Emit(OpCodes.Cpblk)
    ilGenerator.Emit(OpCodes.Ret)
    dm.CreateDelegate(typeof<blitDelegate<'T>>) :?> blitDelegate<'T>

let blit (blitDel:blitDelegate<'T>) dst src byteWidth = blitDel.Invoke(dst, src, byteWidth)

Тогда я вызываю этот код от ученика вот так:

let dst = //get nativeint destination address
let src = //get nativeint source address

let bd = createBlitDelegate<'T>()

let tdst = NativePtr.ofNativeInt<'T> dst
let tsrc = NativePtr.ofNativeInt<'T> src

do blit bd tdst tsrc (uint32 size)
//Program.MemCpy.Invoke(dst.ToPointer(), dst.ToPointer(), uint32 size)

Это приводит к ошибке времени выполнения при blit ( System.Security.VerificationException: операция может дестабилизировать время выполнения. )

Закомментированный код работает хорошо (его можно найти здесь ), но я хотел кодировать его на F # (не на C #).

Причина, по которой я хотел сначала использовать nativeptr<unit>, заключается в том, что это на самом деле тип двух первых аргументов делегата MemCpy (соответствует типу void*), и он хотел имитировать его. *

Edit2:

Основываясь на правке kvb, я изменил свой код, чтобы разместить создание делегата в типе, используя статические члены (например, версию C #), и теперь это работает. Я не использую версию с неуправляемым ограничением, но эту, так как мне действительно нужно скопировать массив структур:

type blitDelegate = delegate of nativeint * nativeint * uint32 -> unit

1 Ответ

2 голосов
/ 29 декабря 2010

Из вашего описания мне не понятно, зачем вам nativeptr<unit>. По сути, nativeptr<'t> - это просто тонкая оболочка над nativeint с некоторыми помощниками для выполнения арифметики с указателем. Поскольку у вас вряд ли будет массив unit s, я не вижу, как это на самом деле вам помогает. Возможно, если вы покажете больше своего кода, вам будет легче дать более удовлетворительный ответ.

EDIT

Я думаю, вы делаете почти все правильно. Однако DynamicMethod, размещенные на анонимном сервере, должны быть проверяемыми, а код операции cpblk никогда не может быть проверен. Попробуйте использовать другой конструктор для DynamicMethod, чтобы разместить его в типе или модуле.

...