更快地以数组形式返回数据的c++接口
faster way to return data as an array interoping c++
这是一个非常干净的解决方案,可以从非托管的c++代码中marsahall一个struct数组。当涉及到简单性时,它是最完美的解决方案,我花了一段时间来理解这个概念,所以在几行代码中,正如你可以看到的c# Main()
,我有一个填充的结构数组准备"收获"..
typedef struct {
int Id;
BSTR StrVal;
}Package;
extern "C" __declspec(dllexport) void dodata(int requestedLength,int StringSize, Package **Packs){
int count;
count=0;
*Packs = (Package*)LocalAlloc(0, requestedLength * sizeof(Package));
Package *Cur = *Packs;
while(count!= requestedLength)
{
Cur[count].StrVal = NULL;
Cur[count].Id = count;
Cur[count].StrVal=SysAllocString(L"abcdefghij");
Cur[count].StrVal[StringSize-1]=count+'0';
++count;
}
}
c# [DllImport(@"ExportStructArr.dll", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void dodata(int requestedLength, int StringSize, out IntPtr csPkPtr);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct csPk
{
public int V;
[MarshalAsAttribute(UnmanagedType.BStr, SizeConst = 10)]
public string testStr;
}
static void Main(string[] args){
int ArrL = 16000;
csPk[] Cpk = new csPk[ArrL];
IntPtr CpkPtr = IntPtr.Zero;
int szPk = Marshal.SizeOf(typeof(csPk));
dodata(ArrL, 10, out CpkPtr);
}
现在我要做的就是:
for (int i = 0; i < Cpk.Length; i++)
{
Cpk[i] = (csPk)Marshal.PtrToStructure(new IntPtr(CpkPtr.ToInt32() + (szPk * i)), typeof(csPk));
}
如您所见,解决方案非常简单问题是使用不安全的或任何类型的数据转换,甚至到字节…
我如何优化它以更好地返回数据?
编辑:链接,我试图从这里的其他答案学习:
- 汉斯·帕桑特的回答
- AbdElRaheim的回答
- supercat的回答
也试过Google: wikipedia, github post by stephentoub
这是一个完整的快速的解决方案来填充对象列表,我已经尽力了我很乐意提出意见和建议。
c++typedef struct _DataPacket
{
BSTR buffer;
UINT size;
} DataPacket;
extern "C" __declspec(dllexport) void GetPacksUnsafe( int size, DataPacket** DpArray )
{
int szr = size;int count=0;
*DpArray = (DataPacket*)CoTaskMemAlloc( szr * sizeof( DataPacket ));
if ( DpArray != NULL )
{
DataPacket* CurPack = *DpArray;
for ( int i = 0; i < szr; i++, CurPack++ )
{
CurPack->size = i;
CurPack->buffer = SysAllocString(L"SomeText00");
CurPack->buffer[9]=i+'0';
}
}
}
c# [DllImport(@"ExportStructArr.dll", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void GetPacksUnsafe(int size, PackU** outPackUArr);
[StructLayout(LayoutKind.Sequential)]
public unsafe struct PackU
{
public char* StrVal;
public int IntVal;
}
public static unsafe List<PackU> PopulateLstPackU(int ArrL)
{
PackU* PackUArrOut;
List<PackU> RtLstPackU = new List<PackU>(ArrL);
GetPacksUnsafe(ArrL, &PackUArrOut);
PackU* CurrentPack = PackUArrOut;
for (int i = 0; i < ArrL; i++, CurrentPack++)
{
RtLstPackU.Add(new PackU(){ StrVal = CurrentPack->StrVal, IntVal=CurrentPack->IntVal});
}
Marshal.FreeCoTaskMem((IntPtr)PackUArrOut);
for (int i = 0; i < 10; i++)
{
Console.WriteLine("{0}", new string(RtLstPackU[i].StrVal));
}
return RtLstPackU;
}
使用代码是尽可能简单的
static unsafe void Main(string[] args)
{
int ArrL = 100000;
List<PackU> LstPackU;
LstPackU = PopulateLstPackU(ArrL);
}
在那里你有一个自定义数据列表,快如子弹子弹…
编辑
使用指针代替字符串:
typedef struct _DataPackCharPnt
{
char* buffer;
UINT IntVal;
} DataPackCharPnt;
extern "C" __declspec(dllexport) void GetPacksPnt( int size, DataPackCharPnt** DpArrPnt )
{
int count = 0;
int TmpStrSize = 10;
*DpArrPnt = (DataPackCharPnt*)CoTaskMemAlloc( size * sizeof( DataPackCharPnt ));
DataPackCharPnt* CurPackPnt = *DpArrPnt;
char dummyStringDataObject[]= "abcdefgHi";
for ( int i = 0; i < size; i++,CurPackPnt++ )
{
dummyStringDataObject[9] = i+'0';
CurPackPnt->IntVal=i;
CurPackPnt->buffer = (char*)malloc(sizeof(char)*TmpStrSize);
strcpy(CurPackPnt->buffer, dummyStringDataObject);
}
}
将填充100k个元素所需的时间从11 ms减少到7 ms
在创建buffer
时是否有可以省略的部分?
-
dummyStringDataObject
的职责是模拟工作,说得到一个文件名,然后用它的值设置缓冲区,所以除了这个额外的时间,这是这个函数的全部目的,返回一些未知的值和字符串的长度…
相关文章:
- 使用JsonCpp将数据返回到带有pybind11的python会在python调用中产生Symbol not foun
- 从函数返回任意简单类型的数据
- 通过 NIF 从C++返回自定义数据结构
- 为什么我们使用在C++中返回数据结构的函数?
- 将传入的网络"char*"数据转换为"uint8_t"并返回的安全方法是什么?
- 如何在模板中返回正确类型的数据?
- H5Tget_member_type() 返回复合 HDF5 数据类型的奇怪值
- 保持排序的数据结构,允许log N插入时间,并且可以返回我在log N中查找的元素的索引
- 如何通过另一个对象中的命令正确地从一个对象返回数据
- 查找存储在二叉搜索树的所有非叶子中的数据总和?(返回整数的独立递归函数
- 在C++中,运算符 sizeof 返回什么数据类型?
- 函数重载并根据相同的输入返回不同的数据类型
- 从新实例的向量中检索数据返回 0
- 类类型中的访问器函数未从 C++ 中的私有数据返回正确的值
- c++ 函数,将数据返回到引用向量
- UNIX域套接字C++服务器无法将数据返回到客户端
- 获取和设置内部数据:返回类型,错误情况下的行为
- 存储在char数组中的双精度数据返回浮点值
- QtCreator QMediaPlayer元数据返回空白QString
- 直接使用变量(数组中的数据返回相同)或与指针一起使用