English 中文(简体)
穿透: C++无管理的阵列
原标题:Improper marshaling: C# array to a C++ unmanaged array

I have the following C# code with a structure definition (CInput), obj definition and init, and a call to a C++ (native) DLL function (that has also been written by me).

//C# code

 public struct CInput
 {

  [MarshalAsAttribute(UnmanagedType.R8)] 
  public double Time;

  [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_R8)]
  public double[] Database;

  /* other similar fields*/

}     

CInput Inputs = new CInput();

/* init of Inputs fields*/

int bfr = Example(ref Inputs); // Example  being the C++ DLL call

Messagebox.Show(bfr.ToString());

第二个参数瓦解有错误,我不知道什么地方。 然后:

//C++ code

struct CInput {

  double Time;                       
  double Database[3650];     
  /*etc*/   
}

int Example(CInput& ObjIn) {

    return ObjIn.Database[0];        // just an example
}

如果我不小心,在数据库中只注明“SafeArray”,我就会在阅读/书写记忆中出现错误,很可能是腐败的。

if "Database" was marshaled as ByValArray everything is fine, the values show up correctly. Unfortunately I get an internal size exception because I have many arrays of that size, therefore I have to go for pointers - but anything with "SizeArray" will bring the following results (with the code just posted):

(C++):

Database[0] = **0**

Database[1..etc] = values of the next parameters in the struct marshaled with ByValArray.

我认为,我应该提到,我需要从C#到C++的同样结构,我不想看任何问题。 So Array in a Struct >>> Array in a Struct.

<>ANY>/strong> 这方面的见解将具有巨大价值。 我一直在寻找时间,我还没有解决办法。

很多人预先表示感谢。

最佳回答

我理解你的问题,你可以使用<代码>ByValArray和SizeConst,因为你的真正结构有许多这样的阵列,导致过度流入。

你认为你需要把点人用在你身上,我同意你的意见。 这里是怎样做的。

在C++方面,你应宣布每一阵列为元素类型点:

struct CInput {
  double *array;
}

您也不妨将阵列的长度列入结构中,以避免过多的硬编码常数。

所有辛勤工作都发生在C#一侧。

public struct CInput
{
    public IntPtr array;
}
...
double[] theArray = new double[3650];
CInput input = new CInput();
input.array = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double))*theArray.Length);
try 
{
    Marshal.Copy(theArray, 0, input.array, theArray.Length);
    //call your C++ function here
}
finally
{
    Marshal.FreeHGlobal(input.array);
}
问题回答
public struct CInput  
{    
    public double Time;    
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3650)] 
    public double[] Database;
}       

CInput Inputs = new CInput();  
int bfr = Example(ref Inputs);

Edit。 如果你需要动态分配数据库阵列,则应修改C++和C#代码。 在C++数据库中,应当被定义为双重数据,并且需要增加一些地方的阵容。 在C#数据库中,应宣布为IntPtr,并使用沼泽地分配。 AllocH 全球方法。 请根据您的要求纠正C++结构,然后根据这一规定确定C#代码。





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签