Pergunta

Eu tenho uma função em C# que está passando uma variedade de estruturas em uma DLL escrita em C ++. A estrutura é um grupo de INTs e, quando leio os dados na DLL, todos os valores saem bem. No entanto, se eu tentar escrever para os elementos de C ++, os valores nunca aparecem quando tento ler, de volta ao C#.

C#

[StructLayout(LayoutKind.Sequential)]
struct Box
{
  public int x;
  public int y;
  public int width;
  public int height;
}

[StructLayout(LayoutKind.Sequential)]
struct Spot
{
  public int x;
  public int y;
}

static void TestCvStructs()
{
  int len = 100;
  Box[] r = new Box[len];
  Spot[] p = new Spot[len];

  for (int i = 0; i < len; i++)
  {
    r[i].x = i*10;
    r[i].y = i * 200;
    r[i].width = r[i].x * 10;
    r[i].height = r[i].y * 100 + r[i].x * 5;

    p[i].x = i * 8;
    p[i].y = i * 12;
  }

  PassCvStructs(len, r, p);

  for (int i = 0; i < len; i++)
  {
    Console.WriteLine("Point/x:{0} Boxes/x{1}", p[i].x, r[i].x );
  }
}

[DllImport(dll)]
private static extern int PassSomeStructs(int count, Box[] boxes, Spot[] points);

C ++

typedef struct Box
{
  int x;
  int y;
  int width;
  int height;
} Box;

typedef struct Spot
{
  int x;
  int y;
} Spot;

CPPDLL_API int PassSomeStructs(int arrayLength, Box *boxes, Spot *points)
{
  for(int i = 0; i < arrayLength; ++i)
  {
    printf("Group:%i\n", i);
    printf("Rect - x:%i y:%i width:%i length:%i\n", boxes[i].x, boxes[i].y, boxes[i].width, boxes[i].height);
    printf("Point - x:%i y:%i\n", points[i].x, points[i].y);
    printf("\n");

    points[i].x = 3;
    boxes[i].x = 1;
  }
  return 0;
}
Foi útil?

Solução 3

Encontrei a resposta postada para outra pergunta: Como Marshall Array de estruturas em C#?

Quando o marechaling aparentemente o padrão é marcar os parâmetros como em. Caso contrário, eles precisam ser explicitamente declarados como fora ou para dentro. Depois de especificar isso explicitamente meu código, o exemplo agora funciona.

Graças ao dele Skeetness para a resposta e para Antonmarkov para a exposição aos marechalas.

private static extern int PassSomeStructs(int count, [In, Out] Box[] boxes, [In, Out] Spot[] points);

Outras dicas

De um Artigo do MDSN Em matrizes de marecha: tente definir o seguinte atributo em seus tipos de matriz. Normalmente, isso é usado para ligar para C# de C ++, mas também pode ser necessário para obter os valores atualizados de volta ao C#.

[DllImport(dll)]
private static extern int PassSomeStructs(int count, 
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] Box[] boxes, 
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] Spot[] points);

Veja também este artigo para um exemplo de bem-sucedido marechaling bidirecional:

http://social.msdn.microsoft.com/forums/en-us/csharplanguage/thread/ff0123d0-506b-4de2-bfb5-f690c9358826/

Você já tentou adicionar a palavra -chave REF/out ao seu C# extern?

Outra idéia é tentar passar em um intptr em vez da própria classe, ou passando -a em -como um intptr ...

Acredito que as estruturas são copiadas, não passadas por referência por padrão.

Honestamente esfaqueando no escuro, mas você ainda não tem respostas, então espero que isso ajude ...

A interop ainda está no estágio "It's Magic" para mim ...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top