Pregunta

Tengo algún código C ANSI estándar que es autoritario. Lo que eso significa es que, aunque tengo la fuente, no puedo traducir a otro idioma ni modificar los argumentos de las llamadas, ya que esas acciones invalidarán la autoridad. Hay más de 150 funciones.

Puedo hacer cambios incidentales, como cambiar los nombres de los archivos de .C a .CPP para que compile utilizando el compilador de C ++ de Visual Studio 2009, lo que he hecho. También se pueden agregar directivas de compilación y similares. También puedo pasar por una capa de envoltorio, si es necesario.

Otra restricción es que mi compañía no quiere que use la palabra clave no segura en cualquier código C #.

Necesito acceder a estas funciones desde un programa de C #.

Una función típica de C / C ++ se ve así:
  doble SomeFunction (double a, double [3] vec, double [3] [3] mat);
Donde los contenidos de la matriz a veces son de entrada, a veces de salida, y raramente ambos.

Primero intenté hacer una DLL no administrada (con las funciones marcadas Extern C). Las funciones con solo argumentos simples (int, double) funcionaron bien, pero no pude determinar cómo ordenar las matrices. (En realidad, encontré un código de ejemplo, pero fue extremadamente complejo e irrazonable duplicarlo 150 veces).

Luego probé dos proyectos dentro de la misma solución, uno en C ++ y el otro en C #. En el proyecto C ++, creé una función administrada que acaba de llamar a la función original que se marcó como no administrada. Esto fue extremadamente limpio y simple, y una vez más, los argumentos simples funcionaron bien. Pero para las matrices, no pude encontrar cómo hacer que los tipos de argumentos coincidan en el límite de C # a C ++:
Argumento '2': no ??se puede convertir de 'double []' a 'double *'
(y como se mencionó anteriormente, no puedo usar inseguro para obtener un puntero).

Ciertamente, lo que estoy tratando de hacer debe ser posible.
¿Cuál es la mejor manera de llegar a estas funciones?
(El código de muestra que utiliza la función anterior sería realmente genial).

¿Fue útil?

Solución

Implementación de muestra C / 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;
}

Ejemplo de uso de C #:

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

Otros consejos

Si no puede hacer que la solución externa y P / Invoke funcione, un envoltorio es probablemente su mejor opción. Cree una DLL de C ++ administrada que use código administrado y no administrado. Agregue una clase .NET a esta DLL que es solo una envoltura delgada sobre las funciones en su DLL de C. Su código C # puede llamar a la clase C ++ .NET, que a su vez avanzará en las funciones de C.

De esta manera, puede escribir la traducción entre .NET y el código no administrado usted mismo, en lugar de confiar en el tiempo de ejecución para que lo haga por usted.

usa swig, generará tu pinvoke por ti

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top