- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我在编码和 PInvoke 方面遇到了一些问题,我必须为现有的 native 应用程序(Oracle Siebel CRM,调用中心集成接口(interface))开发某种驱动程序。从我的角度来看,应用程序的来源是黑盒子。这是两个结构的签名(如 API 描述中所定义)和使用它们的 API 函数:
struct ISC_KeyValue /* Key-Value element */
{
ISC_STRING paramName;
ISC_STRING paramValue;
};
struct ISC_KVParamList /* List of Key-Value parameter */
{
struct ISC_KeyValue* dataItems;
long len;
};
ISCAPI ISC_RESULT CreateISCDriverInstance
/* in */(const ISC_STRING mediaTypeStr,
/* in */ const ISC_STRING languageCode,
/* in */ const ISC_STRING connectString,
/* in */ const struct ISC_KVParamList* datasetParams,
/* out */ ISC_DRIVER_HANDLE* handle);
这里的 ISC_STRING 是宽字符 C++ 字符串(2 字节 Unicode)。 ISC_RESULT 是类似于 HRESULT 类型的整数值。我在将 ISC_KVParamList* datasetParams 编码到 CreateISCDriverInstance 函数时遇到问题,我需要帮助。
这是我对如何整理它的看法:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct IscKeyValue
{
[MarshalAs(UnmanagedType.LPWStr)]
public string ParamName;
[MarshalAs(UnmanagedType.LPWStr)]
public string ParamValue;
}
[StructLayout(LayoutKind.Sequential)]
public struct IscKvParamList
{
public IntPtr DataItems;
[MarshalAs(UnmanagedType.I4)]
public int Len;
}
以及函数本身:
[DllExport("CreateISCDriverInstance", CallingConvention = CallingConvention.StdCall)]
public static int CreateIscDriverInstance([MarshalAs(UnmanagedType.LPWStr)] string mediaTypeStr,
[In,MarshalAs(UnmanagedType.LPWStr)] string languageCode,
[In,MarshalAs(UnmanagedType.LPWStr)] string connectString,
[In, Out] ref IscKvParamList dataParams, [Out] IntPtr handle)
{
var datasetParams =(IscKvParamList)Marshal.PtrToStructure(dataParams,typeof(IscKvParamList));
// Some code here
}
当我尝试执行 PtrToStructure 转换时,出现异常,提示“结构不能是值类。”
问题:如何改进 dataParams 参数的编码
附注额外细节 :1.我确定字符集是Unicode2. 我不知道数组的大小,我不能按值编码它。3. 另外,我有很久以前用 Delphi 编写的此类驱动程序的示例实现:
TNamedParam = record
Name: WideString;
Value: WideString;
end;
TNamedParamList = record
Params: packed array of TNamedParam;
Count: Cardinal;
end;
function CreateISCDriverInstance(const AMediaTypeStr, ALanguageCode, AConnectString: PWideChar; const AParams: TISCNamedParamList; out ADriverHandle: THandle):
HRESULT; begin try ADriverHandle := icISCCommunicationDriver.CreateInstance(AParams).Handle;
Result := SC_EC_OK;
except Result := SC_EC_DRIVER_CREATION_ERR;
end;
end;
以及 AParams 的解析:
procedure JoinISCNamedParamList(const AParamList: TNamedParamList; var LParamList: TISCNamedParamList);
var i:Integer;
begin
LParamList.Count := AParamList.Count;
SetLength(LParamList.Params, LParamList.Count);
for I := 0 to Pred(AParamList.Count) do
begin
LParamList.Params[i].Name := PWideChar(AParamList.Params[i].Name);
LParamList.Params[i].Value := PWideChar(AParamList.Params[i].Value);
end;
end;
在这里可以说结构的布局是顺序的。
最佳答案
问题中的信息不完整。网络搜索显示如下代码:
typedef wchar_t ISC_CHAR
typedef ISC_CHAR* ISC_STRING;
这与您在问题中指出的相符。所以,让我们开始吧。但是,如果您可以提供可以在您的某个头文件中找到的信息,那就更好了。
天真地你的结构应该是:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct IscKeyValue
{
public string ParamName;
public string ParamValue;
}
[StructLayout(LayoutKind.Sequential)]
public struct IscKvParamList
{
public IscKeyValue[] DataItems;
public int Len;
}
不需要您使用的 MarshalAs
,因为默认编码就足够了。
但是编码器不会处理结构中的数组。所以我认为你需要这样做:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct IscKeyValue
{
public IntPtr ParamName;
public IntPtr ParamValue;
}
[StructLayout(LayoutKind.Sequential)]
public struct IscKvParamList
{
public IntPtr DataItems;
public int Len;
}
至于函数,翻译为:
[DllExport("CreateISCDriverInstance", CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Unicode, ExactSpelling = true)]
public static int CreateIscDriverInstance(
string mediaTypeStr,
string languageCode,
string connectString,
[In] ref IscKvParamList dataParams,
out IntPtr handle
);
现在是乐趣。准备 IscKvParamList
参数。
从 IscKeyValue
数组开始:
IscKeyValue[] KeyValueArr = new IscKeyValue[...];
for (int i = 0; i < KeyValueArr.Length; i++)
{
KeyValueArr[i].ParamName = Marshal.StringToCoTaskMemUni(...);
KeyValueArr[i].ParamValue = Marshal.StringToCoTaskMemUni(...);
}
现在是 IscKvParamList
。我想我会固定阵列。像这样:
GCHandle ArrHandle = GCHandle.Alloc(KeyValueArr, GCHandleType.Pinned);
try
{
IscKvParamList dataParams;
dataParams.DataItems = ArrHandle.AddrOfPinnedObject();
dataParams.Len = KeyValueArr.Length;
int retval = CreateIscDriverInstance(
mediaTypeStr,
languageCode,
connectString,
ref dataParams,
out handle
);
}
finally
{
ArrHandle.Free();
}
您必须确保记得释放在调用 Marshal.StringToCoTaskMemUni
时分配的非托管内存。
关于c# - PInvoke DllExport : structure marshaling failure,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27034263/
这是我第一次在结构中使用结构。我在编译我的程序时遇到了这个错误。错误:字段“结果”的类型不完整。 错误是指这行代码。-->结构result_t结果; 有什么帮助吗? :)谢谢。 typedef str
typedef struct mensagem { int sender ; int receiver ; char *text ; } *Item ; typedef str
我正在使用 ExpressionEngine 和 Structure 附加组件的最新版本。 我正在寻找有关生成 4 项导航栏的帮助,其中两项位于不同的结构级别。 我的结构行如下所示: 服务(父) --
我正在处理一个非常大的数据集。本质上,我将处理数百万条记录并将值存储到数据集中。 每次我存储一个值时,我必须首先检查以确保该值不在数据结构中。如果值在数据结构中,我必须更新(或删除/添加)记录以更新计
我正在尝试分别使用视频帧和音频来分析视频,我想出了一个看起来像这样的模型 现在,我将训练数据分成两个生成器 - 一个用于视频,一个用于音频。我必须进一步将生成器分成两半,我认为这是我遇到错误的地方。因
我有一个创建 N 个进程的程序,每个进程创建 M 个线程。 我还有一个结构需要传递给线程函数。 当我像这样创建 M 个线程时: thread_args_t** thread_arg = malloc(
我正在试图弄清楚如何实现一个等待事件发出信号的函数。指针由DLL函数返回,该函数是存储3个项的结构。其中两个是句柄,它们只是指针,最后是一些随机的未使用的指针。我真的不确定这应该如何格式化,因为我两个
根据PLCOpen、IEC-61131标准,是否可以在声明中初始化结构体? 我正在考虑类似于 this C++ question 的事情. 最佳答案 您可以在结构声明时向结构变量添加默认值。您还可以在
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
在纯 C 中工作,将结构嵌套在其他结构或指向结构的指针中更好。使用指针可以更容易地实现良好的对齐,但是访问内部结构需要额外的取消引用。只是具体地说: typedef struct {
我正在使用 Qt Creator 开发应用程序。 我不是一个好的C++程序员,所以可能会有概念上的错误等。 我在复制结构数组并返回结构时遇到问题。 有很多与类似标题相关的解决方案,但无法解决我的问题。
我正在尝试使用带水印的 dropDuplicate 函数对流数据进行重复数据删除。我目前面临的问题是我必须为给定记录设置两个时间戳 一个是事件时间戳 - 从源创建记录的时间戳。 另一个是传输时间戳 -
很难说出这里问的是什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或言辞激烈,无法以目前的形式合理回答。如需帮助澄清此问题以便可以重新打开,visit the help center . 10年前关
我尝试构建一个嵌套循环,用于创建 2 维零矩阵来解决 LCS 问题(动态规划)。这后来用于计算 Rouge-L 分数(输入是张量,而不是字符串),但它总是出错引发 ValueError: The tw
我曾多次使用 HDFS 和 Kafka,我注意到 Kafka 比 HDFS 更可靠。因此,现在使用 Spark-structured-streaming 时,我很惊讶检查点仅适用于 HDFS。使用 K
C11,6.7.2.1 结构和 union 说明符,约束,3(添加了强调): A structure or union shall not contain a member with incomple
在 emacs lisp 中,各种树结构是常见的。 custom.el通过:type提供论据 defcustom定义自定义变量的预期形状的标准方法。但是有没有一种标准的方法来验证一些随机 emacs
我在网上遇到了以下面试问题。 描述一个数据结构,其中 getValue(int index)、setValue(int index, int value) 和 setAllValues(int val
我正在使用 sqldf 对一个巨大的文件进行子集化。以下命令为我提供了一个 100 行和 42 列的 data.frame。 first <- read.csv.sql("first.txt", se
来自这里的 C++ 背景。我需要为我的一门类(class)编写 C 语言,但我从未接触过这一类(class)。这两个声明之间有什么区别?为什么要包含 struct 关键字?有不同的含义吗?它们在 C+
我是一名优秀的程序员,十分优秀!