- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的问题已经非常非常接近解决方案,但我需要一些关于收尾工作的指导,以使一切正常。在过去的一周里,我学到了很多关于
作为引用,我上周就同一主题问了一个类似的问题,但由于我这边的巨大疏忽,我问错了问题。
我正在尝试使用一个非托管的 c++ dll,它是与连接的设备进行通信的 API。我已经成功创建了包装器和大多数其他函数调用,但最后一个让我发疯。
一些背景信息(可能不需要回答这个问题 - 请记住我当时的基本思维过程是有缺陷的)在这里:Calling un-managed code with pointer (Updated)
在我原来的问题中,我问的是创建一个 IntPtr 到一个包含一个 struct(2) 数组的 struct(1).... 事实上,struct(1) 根本不包含一个数组,它包含指向数组的指针。
这是我尝试实现的 API 的文档作为引用:
extern “C” long WINAPI PassThruIoctl
(
unsigned long ChannelID,
unsigned long IoctlID,
void *pInput,
void *pOutput
)
// *pInput Points to the structure SCONFIG_LIST, which is defined as follows:
// *pOutput is not used in this function and is a null pointer
typedef struct
{
unsigned long NumOfParams; /* number of SCONFIG elements */
SCONFIG *ConfigPtr; /* array of SCONFIG */
} SCONFIG_LIST
// Where:
// NumOfParms is an INPUT, which contains the number of SCONFIG elements in the array pointed to by ConfigPtr.
// ConfigPtr is a pointer to an array of SCONFIG structures.
// The structure SCONFIG is defined as follows:
typedef struct
{
unsigned long Parameter; /* name of parameter */
unsigned long Value; /* value of the parameter */
} SCONFIG
这是我目前定义的结构体定义
[StructLayout(LayoutKind.Sequential)] // Also tried with Pack=1
public struct SConfig
{
public UInt32 Parameter;
public UInt32 Value;
}
[StructLayout(LayoutKind.Sequential)] // Also tried with Pack=1
public struct SConfig_List
{
public UInt32 NumOfParams;
public IntPtr configPtr;
public SConfig_List(UInt32 nParams, SConfig[] config)
{
this.NumOfParams = nParams;
// I have tried these 2 lines together
IntPtr temp = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MyNameSpace.SConfig)) * (int)nParams);
this.configPtr = new IntPtr(temp.ToInt32());
// I have tried this by itself
// this.configPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MyNameSpace.SConfig)) * (int)nParams);
// and this line
// this.configPtr = Marshal.AllocHGlobal(sizeof(SConfig)*(int)nParams); // this only complies with unsafe struct
}
}
这是将这些设置为变量并调用与 API 接口(interface)的函数的代码片段
SConfig[] arr_sconfig;
arr_sconfig = new SConfig[1];
arr_sconfig[0].Parameter = 0x04;
arr_sconfig[0].Value = 0xF1;
SConfig_List myConfig = new SConfig_List(1, arr_sconfig);
m_status = m_APIBox.SetConfig(m_channelId, ref myConfig);
最后,这里是将此信息传递给 dll 的函数:
public APIErr SetConfig(int channelId, ref SConfig_List config)
{
unsafe
{
IntPtr output = IntPtr.Zero; // Output not used, just a null pointer for this function
// These 2 lines of code cause API dll to yell about invalid pointer (C# is happy but it doesnt work with dll)
// IntPtr temp = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(J_2534_API.SConfig_List)));
// IntPtr input = new IntPtr(temp.ToInt32());
// The following 2 lines only compile with unsafe - but API dll "likes" the pointer - but I am not getting desired results
// The dll is properly getting the Number of Parameters (NumOfParams), but the data within the array is not being
// referenced correctly
IntPtr input = Marshal.AllocHGlobal(sizeof(SConfig_List)); // Only works with unsafe
Marshal.StructureToPtr(config, input, true);
APIErr returnVal = (APIErr)m_wrapper.Ioctl(channelId, (int)Ioctl.SET_CONFIG, input, output);
return returnVal;
}
}
在我意识到我对基本思想的巨大疏忽之前,我从来没有让 C# 高兴过,要么我的语法错误,代码无法编译,要么编译但给出运行时错误(甚至从未调用外部 dll)
这些问题都在我身后。代码现在可以正常编译,并且执行时没有任何运行时错误。此外,我正在使用的 dll 具有日志记录功能,所以我可以看到我实际上调用了正确的函数。我什至正确地向它传递了一些数据。函数正在正确读取 NumOfParams 变量,但结构数组似乎是垃圾数据。
我在这里阅读了一篇非常有用的文章:http://limbioliong.wordpress.com/2012/02/28/marshaling-a-safearray-of-managed-structures-by-pinvoke-part-1/
我一直在阅读 MSDN,但到目前为止我还没有找到使这件事起作用的神奇代码组合,所以我再次寻求帮助。
我很确定我的问题是我没有正确设置 IntPtr 变量,它们没有指向内存中的正确区域。
我尝试过各种不安全和安全代码的组合。另外,我知道我此时并没有明确释放内存,所以关于这方面的指示也会有所帮助。在我的研究中,这里有一些可能有用的想法,但我似乎无法让它们恰到好处
[MarshalAs(UnmanagedType.LPWStr)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst=...)]
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst=100)]
最后一个问题:我假设由于 c++ 声明是无符号长型,那么 UInt32 是 C# 中的正确类型吗?
最佳答案
代码段中的 SConfig_List 构造函数有很多问题。最大的问题是它为数组分配内存但也完全忘记了复制结构。因此, native 代码可以正常获取指针,但会查看未初始化的内存。您可以这样修复它:
public SConfig_List(SConfig[] config) {
this.NumOfParams = config.Length;
int size = Marshal.SizeOf(config[0]);
IntPtr mem = this.configPtr = Marshal.AllocHGlobal(size * config.Length);
for (int ix = 0; ix < config.Length; ++ix) {
Marshal.StructureToPtr(config[ix], mem, false);
mem = new IntPtr((long)mem + size);
}
}
请务必不要在调用完成后再次调用 Marshal.FreeHGlobal(),否则您将泄漏内存。
避免编码 SConfig_List 的最简单方法是为 C 函数提供更好的声明:
[DllImport(...)]
private static extern ApiErr PassThruIoctl(
int channelID,
uint ioctlID,
ref SConfig_List input,
IntPtr output);
这使得一个像样的包装器方法看起来像这样:
public APIErr SetConfig(int channelId, SConfig[] config) {
var list = new SConfig_List(config);
var retval = PassThruIoctl(channelId, Ioctl.SET_CONFIG, ref list, IntPtr.Zero);
Marshal.FreeHGlobal(list.configPtr);
return retval;
}
关于c# - 编码(marshal)结构数组和 IntPtr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19753653/
在编程环境中是哪一个?有区别吗?我已经看到了这两种方式,我不想在我的代码中拼错它。 最佳答案 编码(marshal)是工作图 block ;例如,消防编码(marshal)或美国编码(marshal)
我有以下结构: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct WAVEHDR { in
我找不到以下问题的明确答案:如果一个 COM 类是线程安全的,即它被标记为 Both 或 Free,我真的需要编码它的对象接口(interface)以将它传递给另一个线程吗?相同的过程?我不问两个线程
在编译 C# ASP.NET 应用程序时,我从 Visual Studio 2008 中收到奇怪的警告。谁能告诉我这个警告的含义(如果可能的话,用几个音节的词)? At least one of th
TL;DR:MongoDB 驱动程序是否提供了编码和解码文档单个字段的功能? 这是一个非常简单的问题,但这里有一些上下文: 我有一个工作人员负责在 2 个独立的数据库之间同步数据。当它接收到事件消息时
是否可以在使用自定义编码(marshal)拆收器的结构上使用 Marshal.SizeOf()? 例如: struct Abcde { public int test1; [MarshalAs
我有一张 map :[]map[string]string . 将结果填充到 json.marshal()兼容的对象。输出: [ { "key1": "val1", "key2":
如何在没有根元素的情况下进行编码(marshal)? type Ids struct { Id []string `xml:"id"` } IdsStr, _ := xml.Marshal(&Id
我有这个 C++ 代码: extern "C" __declspec(dllexport) VOID AllocateFoo(MY_DATA_STRUCTURE** foo) { *foo =
我创建了 map[string]interface{} 并且我想通过 2 个重置服务之间的映射传递多种类型。 每次我编码时,我都会在应该包含 reflect.Type 的字段中得到空映射。 Servi
我有一个托管的 .Net 类,它创建了我需要确保正确清理的非托管资源。 我有一个顺序结构: [StructLayout(LayoutKind.Sequential)] struct FooBar {
我在用 val akkaV = "2.2.3" val sprayV = "1.2.0" Seq( "io.spray" % "spray-can" % spra
我正在使用 Castor 编码/取消编码我的 Java 对象,其中一个对象包含一个 EnumMap。Castor 可以编码(marshal)/解封 EnumMaps 吗?我有一个带有一些嵌套 Hash
错误:com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException:无法编码类型类 [Ljava.lang.Strin
我们在 netbeans 中做了一次 cleanbuild,检查了 jdk 版本并在服务器上部署了所有内容,但仍然出现以下错误。有人可以帮忙吗? javax.servlet.ServletExcept
我想知道是否可以对我的类进行注释,以便编码器第一次遇到对象时,它会生成适当类型的 XML 元素,但任何其他对该对象的后续引用都将具有 XML IDREF条目已创建? 最佳答案 您可以利用 JAXB 的
我正在从现有代码构建一个通用类库,但我收到了一些编译器警告,提示我终其一生都不知道该如何处理。 我有这样的代码: void SomeMethod(Object data) { var size =
我在编码我的 JAXBElement 时遇到了这个异常,它有几个子元素。我如何弄清楚如何查明导致此异常的子元素? java.lang.NullPointerException at com.s
本文整理了Java中org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller.marshall()方法的一些代码示例,展示
我最近已经问了一个有关 JAXB 的问题,可以在以下位置找到:How to marshal/unmarshal Java objects with private fields using JAXB
我是一名优秀的程序员,十分优秀!