Pergunta

Eu tenho algum código C padrão ANSI que é autoritária. O que isto significa é que, embora eu tenho a fonte, eu não posso traduzir para outro idioma, nem modificar chamando argumentos, como aquelas ações invalidaria a autoridade. Existem mais de 150 funções.

Eu posso fazer alterações acessórias, tais como mudar os nomes de arquivo de .C para .CPP para que ele compila usando o compilador Studio 2009 do Visual C ++, o que eu fiz. directivas do compilador e tal, podem também ser adicionados. Eu também pode passar por uma camada de invólucro, se necessário.

Outra restrição é a minha empresa faz não quer que eu use o inseguro palavra-chave em qualquer código C #.

eu preciso para chegar a estas funções de um programa C #.

Um típico C / C ++ função esta aparência:
double SomeFunction(double a, double[3] vec, double[3][3] mat);
Onde o conteúdo da matriz são, por vezes, de entrada, por vezes, de saída, e raramente ambos.

A primeira vez que tentei fazer uma DLL não gerenciada (com as funções marcadas Extern C). Funções com apenas argumentos simples (int, Double) funcionou bem, mas eu não poderia determinar como empacotar os arrays. (Na verdade, eu encontrei um código de exemplo, mas era extremamente complexa e razoável para duplicar 150 vezes).

Então eu tentei dois projetos dentro da mesma solução, um em C ++ e outra em C #. Em projecto do C ++, eu criei uma função gerenciada que apenas chamou a função original, que foi marcado como não gerenciado. Este foi extremamente limpo e simples, e novamente, argumentos simples funcionou bem. Mas para arrays, eu não poderia encontrar como fazer os tipos de argumentos corresponder através do C # para C ++ limite:
Argument '2': cannot convert from 'double[]' to 'double*'
(E como mencionado acima, eu não posso usar inseguro para obter um ponteiro).

Com certeza o que eu estou tentando fazer deve ser possível.
Qual é a melhor forma de chegar a essas funções?
(Exemplo de código usando a função acima seria muito legal.)

Foi útil?

Solução

Amostra C / implementação C ++:

extern "C" __declspec(dllexport)
double SomeFunction(double a, double vec[3], double mat[3][3]) {
  double sum = a;
  for (int ix = 0; ix < 3; ++ix) {
    sum += vec[ix];
    for (int iy = 0; iy < 3; ++iy) {
      sum += mat[ix][iy];
    }
  }
  return sum;
}

C # Exemplo de uso:

private void Form1_Load(object sender, EventArgs e) {
  double[] vec = new double[3];
  double[,] mat = new double[3, 3];
  for (int ix = 0; ix < 3; ++ix) {
    vec[ix] = ix;
    for (int iy = 0; iy < 3; ++iy) {
      mat[ix, iy] = (ix + 1) * iy;
    }
  }
  double sum = SomeFunction(1, vec, mat);
}
[System.Runtime.InteropServices.DllImport("cpptemp8.dll")]
private static extern double SomeFunction(double a, double[] vec, double[,] mat);

Outras dicas

Se você não pode obter o extern e solução de P / Invoke para o trabalho, um invólucro é provavelmente a sua melhor aposta. Criar uma DLL C ++ gerenciado que usa tanto código gerenciado e não gerenciado. Adicionar uma classe .NET para esta DLL que é apenas um invólucro fino sobre as funções na sua DLL C. Seu código C # pode chamar a classe C ++ .NET, que por sua vez para a frente nas funções C.

Desta forma, você pode escrever a tradução entre NET e código não gerenciado mesmo, em vez de confiar no tempo de execução para fazer isso por você.

uso gole, ele irá gerar o seu pinvoke para você

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