faster way to return data as an array interoping c++

爱⌒轻易说出口 提交于 2019-11-28 14:28:53

this is a complete blazing fast solution to populate a list of objects, i did my best and i will be happy to have comments and suggestions.

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;
    }

using the code is as simple as it could possibly be

    static unsafe void Main(string[] args)
    {
        int ArrL = 100000;
        List<PackU> LstPackU;
        LstPackU = PopulateLstPackU(ArrL);
    }

there you have a list of custom data as fast as a bullet..

EDIT

using pointers instead of strings :

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);

    }
}

reduced the time taken from 11 to 7 ms populating 100k elements

is there any part of creating the buffer i could omit ?

  • the duty of dummyStringDataObject is to simulate work, say getting a file name then set the buffer with its value, so except for this extra time which is the whole purpose of this function, to return some unknown values and lengths of the strings...

could you optimize it even further ?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!