Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从C#到C+的数组+;然后返回,没有不安全的代码_C#_C++_Arrays_Unity3d - Fatal编程技术网

从C#到C+的数组+;然后返回,没有不安全的代码

从C#到C+的数组+;然后返回,没有不安全的代码,c#,c++,arrays,unity3d,C#,C++,Arrays,Unity3d,我知道这个问题已经被问过了,可能会被认为是重复的,但在阅读了其他答案后,我仍然感到困惑,不理解其中提供的解释 如果有人能提供一个示例代码和一些解释,我将不胜感激 我正在完成以下任务: 我在Unity中有一个纹理/纹理(无法从驱动器加载,动态生成),并将其转换为数组。它可以是int、byte或float的数组 目前,我用C#做目标检测,但我想让它更快。因此,我想做以下工作。 访问C++代码(从DLL,我刚刚开始我的旅程用C++),并运行一个方法,它将采取我的输入数组,做计算,并返回一个新的数组(旧

我知道这个问题已经被问过了,可能会被认为是重复的,但在阅读了其他答案后,我仍然感到困惑,不理解其中提供的解释

如果有人能提供一个示例代码和一些解释,我将不胜感激

我正在完成以下任务:
我在Unity中有一个纹理/纹理(无法从驱动器加载,动态生成),并将其转换为数组。它可以是int、byte或float的数组

目前,我用C#做目标检测,但我想让它更快。因此,我想做以下工作。
访问C++代码(从DLL,我刚刚开始我的旅程用C++),并运行一个方法,它将采取我的输入数组,做计算,并返回一个新的数组(旧的未修改)到C代码。p> 或者,我可以输入两个数组(首选),其中一个数组被修改。
输出数组不必每次都创建,它可以被覆盖。 我不能在C#中使用不安全代码,因为这是出于资产目的(兼容性问题)

模型代码

C#
create arrays aOne,aTwo;
SomeC++Method(aOne,ref aTwo)
or 
aTwo = SomeC++Method(aOne,aTwo)
or 
aTwo = SomeC++Method(aOne) // variant where aTwo is created in C++

SomeC++MethodToDeAllocateMemory() //so there is no memory leak

C++
SomeC++Method(aOne,aTwo)
  for (xyz)
   do someting
  return modified aTwo
SomeC++MethodToDeAllocateMemory()
  release memory
using UnityEngine;
using System.Runtime.InteropServices;

public class Test : MonoBehaviour {

    [DllImport("ArrayFilling", CallingConvention = CallingConvention.Cdecl)]
    public static extern bool PopulateArray([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] float[] floats, int length);

    int length = 4000000; //corresponds to 2000x2000 texture of grayscale values

    void Start()
    {
        //create new array
        float[] floats = new float[length];

        //used for speed test
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

        //check internal method speed
        sw.Start();
        //floats array gets update here
        Populate(ref floats);
        sw.Stop();
        Debug.Log("internal: " + sw.ElapsedMilliseconds);
        sw.Reset();

        //check external method speed
        sw.Start();
        //floats array gets updated here
        PopulateArray(floats, length);
        sw.Stop();
        Debug.Log("external: " +sw.ElapsedMilliseconds);

    }

    void Populate(ref float[] floats)
    {
        for (int i = 0,n = length; i<n;i++)
        {
            floats[i] = i;
        }
    }
}
我在这里找到了这个问题的答案:

样品溶液:

c++代码:

extern "C" __declspec(dllexport) bool PopulateArray(float* floats, int length)
{
    for (int i = 0; i < length; ++i)
    {
        floats[i] = i;
    }

    return true;
}
extern“C”\u declspec(dllexport)bool PopulateArray(float*float,int-length)
{
对于(int i=0;i
C#代码

C#
create arrays aOne,aTwo;
SomeC++Method(aOne,ref aTwo)
or 
aTwo = SomeC++Method(aOne,aTwo)
or 
aTwo = SomeC++Method(aOne) // variant where aTwo is created in C++

SomeC++MethodToDeAllocateMemory() //so there is no memory leak

C++
SomeC++Method(aOne,aTwo)
  for (xyz)
   do someting
  return modified aTwo
SomeC++MethodToDeAllocateMemory()
  release memory
using UnityEngine;
using System.Runtime.InteropServices;

public class Test : MonoBehaviour {

    [DllImport("ArrayFilling", CallingConvention = CallingConvention.Cdecl)]
    public static extern bool PopulateArray([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] float[] floats, int length);

    int length = 4000000; //corresponds to 2000x2000 texture of grayscale values

    void Start()
    {
        //create new array
        float[] floats = new float[length];

        //used for speed test
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

        //check internal method speed
        sw.Start();
        //floats array gets update here
        Populate(ref floats);
        sw.Stop();
        Debug.Log("internal: " + sw.ElapsedMilliseconds);
        sw.Reset();

        //check external method speed
        sw.Start();
        //floats array gets updated here
        PopulateArray(floats, length);
        sw.Stop();
        Debug.Log("external: " +sw.ElapsedMilliseconds);

    }

    void Populate(ref float[] floats)
    {
        for (int i = 0,n = length; i<n;i++)
        {
            floats[i] = i;
        }
    }
}
使用UnityEngine;
使用System.Runtime.InteropServices;
公共课堂测试:单一行为{
[DllImport(“ArrayFilling”,CallingConvention=CallingConvention.Cdecl)]
公共静态外部bool PopulateArray([Marshallas(UnmanagedType.LPArray,SizeParamIndex=1)]float[]floats,int-length);
int length=4000000;//对应于灰度值的2000x2000纹理
void Start()
{
//创建新阵列
浮动[]浮动=新浮动[长度];
//用于速度测试
System.Diagnostics.Stopwatch sw=新的System.Diagnostics.Stopwatch();
//检查内部方法速度
sw.Start();
//浮动数组在此处得到更新
填充(参考浮动);
sw.Stop();
Debug.Log(“内部:+sw.elapsedmillyses”);
sw.Reset();
//检查外部方法速度
sw.Start();
//浮动数组在此处更新
PopulateArray(浮动、长度);
sw.Stop();
Debug.Log(“外部:+sw.elapsedmillyses”);
}
空心填充(参考浮动[]浮动)
{

对于(int i=0,n=长度;i).NET和C++之间的p/INKEKE支持是相当好的。通常它是用<代码> [dLimPurt]声明一些<代码> ExtNe>代码>方法。告诉运行库在哪里找到外部DLL。当数组通过时,关键问题是谁在分配它们。如果C代码是分配它们的,那么通常可以将它们传递进去,例如这里:如果C++代码分配它们,那么你的C代码需要在指针中进行对话,这意味着<代码>不安全> /COD>如果可能的话:让C代码拥有数组

如果数组与任何可用调用都不完全匹配-或者您需要对数组应用偏移量-那么您可以声明
extern
方法以获取
IntPtr
或一些
int*
等,但是您又回到了
不安全的
位置。您可以使用
fixed
将引用转换为指针,即.
fixed(int*ptr=arr){SomeExternalCall(ptr+offset,arr.Length-offset);}
。但如果可能,使用简单的“传递数组”方法更简单

注意,如果方法不同步,即如果C++代码将保持指针的某个时间,那么您需要手动通过“<代码> GCHandle < /COD>”来排列数组。P/Unjk代码知道在一个单一的<代码> ExtNe>/Cudio>调用时,(如<代码>固定< /COD> >在上面的示例中,将数组插入一个数组)。但是,它不能保证在调用完成后不移动它——这会使C++代码的指针保持不可靠。<代码> GCHandle <代码>解决了这个问题,通过将对象钉在适当的位置以满足您需要的任何时间。


但是,C即使在使用100%安全代码时也不坏,如果你的C++实现还没有写出来,我建议首先要改进C实现,以使效率更高。

< P>在.NET和C++之间的P/Unk支持很好,通常是声明一些<代码>外部
使用
[DllImport]的方法告诉运行库在哪里找到外部DLL。当数组通过时,关键问题是谁在分配它们。如果C代码是分配它们的,那么通常可以将它们传递进去,例如这里:如果C++代码分配它们,那么你的C代码需要在指针中进行对话,这意味着<代码>不安全> /COD>如果可能的话:让C代码拥有数组

如果数组与任何可用调用都不完全匹配-或者您需要对数组应用偏移量-那么您可以声明
extern
方法以获取
IntPtr
或一些
int*
等,但是您又回到了
不安全的
位置。您可以使用
fixed
将引用转换为指针,即.
fixed(int*ptr=arr){SomeExternalCall(ptr+offset,arr.Length-offset);}
。但如果可能,使用简单的“传递数组”方法更简单

注意,如果方法不同步,即如果C++代码将保持指针的某个时间,那么您将需要手动通过“<代码> GCHandle < /COD>”来排列数组。