c# - 将浮点指针作为 IntPtr 传递(pinvoke)

好的,我有一个 DLL 函数声明为:

[DllImport(mDllName, EntryPoint = "SetParam")]
public static extern bool setParam(string param_name, ref IntPtr param_value);

此函数接受许多不同的参数,即在 C++ 中,这就是您使用它的方式。

int i=2;
setParam("width", &i);

float k=2.5f;
setParam("factor", &f);

所以我试图声明一个 C# 函数来调用这个 DLL api,我有一个用于指向整数大小写的指针:

public static void setWidth(int width)
{
    IntPtr w = new IntPtr(width);
    setParam("width", ref w);
}

但是我不知道如何做第二个,我将一个指向 float 的指针作为 IntPtr 传递。有什么想法吗?

public static void setFactor(float f)
{
    IntPtr w = new IntPtr(f); // WHAT GOES HERE??
    setParam("factor", ref w);
}

最佳答案

除非组合太多,否则最好的方法是简单地为各种参数类型设置多个 DllImport。例如:

[DllImport(mDllName, EntryPoint = "SetParam")]
public static extern bool setParamInt32(string param_name, ref int param_value);

[DllImport(mDllName, EntryPoint = "SetParam")]
public static extern bool setParamSingle(string param_name, ref float param_value); 

然后您可以正确地调用它们

var intVal = 42;
setParamInt32("param", ref intVal);

var floatVal = 42.0f;
setParamSingle("param", ref floatVal);

在任何一种情况下使用 ref IntPtr 都是错误的 - 它起作用的唯一原因是在 32 位应用程序中,IntPtr 在内部是一个 32 位整数。但是,它应该是一个指针。正确的用法应该是这样的:

[DllImport(mDllName, EntryPoint = "SetParam")]
public static extern bool setParam(string param_name, IntPtr param_value); 

请注意,ref 不存在 - IntPtr 已经是一个间接寻址。

要调用它,您需要分配一些内存,并获取指向它的指针 - 或者,使用 GCHandle 直接引用托管对象:

var intValue = 42;
var handle = GCHandle.Alloc(intValue, GCHandleType.Pinned);
setParam("param", handle.AddrOfPinnedObject());

当然,请确保正确处理托管句柄 - 固定句柄对 GC 来说是一个巨大的痛苦。

手动将数据复制到非托管内存并返回也不是很难:

var ptr = Marshal.AllocCoTaskMem(sizeof(int));

try
{ 
  Marshal.WriteInt32(ptr, 42);

  setParam("param", ptr);

  // If you need to read the value back:
  var result = Marshal.ReadInt32(ptr);
}
finally
{
  Marshal.FreeCoTaskMem(ptr);
}

但除非您有充分的理由不这样做,否则我只会坚持使用自动编码。

https://stackoverflow.com/questions/32220782/

相关文章:

c# - 如何使用 LinQ 按值分组获取字典中的键列表

date - 同步系统时间和日期的批处理文件

c# - 使用 UpdateAsync 方法 ASP.NET Entity Framework

docker - 学习 docker 的先决条件

css - 选择器属性中的手写笔迭代

c# - 使用 Prism 库将 View 注入(inject) TabControl

shopify - Liquid 中的逗号分隔列表

git - 在 git 中恢复大多数前 n 个提交

selenium - 如何 'click' 单选按钮 -> 需要 xPath

r - 在 R 中将字符串拆分为固定长度元素的最快方法