- https://learn.microsoft.com/en-us/dotnet/standard/native-interop/type-marshalling
- https://learn.microsoft.com/en-us/dotnet/framework/interop/marshalling-classes-structures-and-unions
- https://learn.microsoft.com/en-us/dotnet/framework/interop/default-marshalling-for-strings
export a m-function as a DLL to C# which reads a csv file
8 次查看(过去 30 天)
显示 更早的评论
I want to export a m-function as a DLL to C# which reads a csv file.
function fileID = simpleRead(fileName) %#codegen
fileID = fopen(fileName, 'r');
end
I created a DLL using MATLAB Coder and char 1x:Inf as the input type (recommended by the example call).
This is the C# client:
class Programm
{
[DllImport("simpleRead.dll")]
public static extern double simpleRead(string inStr);
static void Main()
{
double res = simpleRead("test2DArray.csv");
}
}
The CSV file is placed in the project folder (using VS22) and the DLL is placed in the same folder as the client.exe.
When I run the client, it gives me the error
System.AccessViolationException: "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
I think this is a problem with the input type. So how can I hand a csv file to my DLL functiuon in C#?
Best regards!
Sören
0 个评论
回答(1 个)
Harsha Vardhan
2024-2-16
编辑:Harsha Vardhan
2024-2-16
Hi,
I see that you are trying to call a user-defined MATLAB function from C#. This can be done 3 ways.
1) Use a MATLAB Coder: This is the way you are currently working on. In addition to the 'dll', the MATLAB coder also generates header (.h) files and definition (.c) files of the MATLAB function. These files can be found in the codegen\dll\simpleRead folder starting from the current folder. In this case, the generated simpleRead.h contains the below declaration of the MATLAB function.
/* Include Files */
#include "rtwtypes.h"
#include "simpleRead_types.h"
#include <stddef.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Function Declarations */
extern double simpleRead(const emxArray_char_T *fileName);
As seen in the documentation here: https://www.mathworks.com/company/technical-articles/generating-c-code-from-matlab-for-use-with-java-and-net-applications.html , review the C data type of the function's arguments and translate them into a .NET data type.This step is important, as you will have to write a declaration of your function in .NET language. Please check the generated file simpleRead_types.h in the same folder. It contains the definition of the function's input structure.
struct emxArray_char_T {
char *data;
int *size;
int allocatedSize;
int numDimensions;
boolean_T canFreeData;
};
So, in the declaratuon of this function in C#, the input data type must match the above structure. So, you may have to create a similar structure in C# and use it in the decalation and the function call of the simpleRead function. Please check a sample declaration in C# below.
public struct emxArray_char_T
{
public IntPtr data;
public IntPtr size;
public int allocatedSize;
public int numDimensions;
[MarshalAs(UnmanagedType.U1)]
public bool canFreeData;
}
[DllImport("simpleRead.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern double simpleRead(ref emxArray_char_T fileName);
This mapping from the 'C' struct to a C# struct is called Type Marshalling. For more details, you may check the documentation here:
2) Use the MATLAB Compiler SDK: You can check its documentation here: https://www.mathworks.com/help/compiler_sdk/dotnet/integrate-simple-matlab-function.html
In this method, using 'compiler.build.dotNETAssembly' from MATLAB compiler SDK, convert the MATLAB function to a method of a .NET class and wrapped the class in a .NET assembly. This produces a 'SimpleRead.dll'. You may check the sample command below.
buildResults = compiler.build.dotNETAssembly('simpleRead.m', ...
'AssemblyName','SimpleRead', ...
'ClassName','SimpleReadClass');
After that, use the below C# code to pass the file name to the MATLAB function inside the 'SimpleRead.dll' and receive the output from the called function. Following the above documentation, in the Visual Studio Project, add reference to 'MWArray API'. Similarly, add a reference to the generated 'SimpleRead.dll'.
using System;
using MathWorks.MATLAB.NET.Utility;
using MathWorks.MATLAB.NET.Arrays;
using SimpleRead;
class ClientForSimpleRead
{
#region MAIN
[STAThread]
static void Main(string[] args)
{
try
{
// Create a new simple read object
SimpleReadClass simpleReadClass = new SimpleReadClass();
String inputFile = "input.csv";
MWArray result = simpleReadClass.simpleRead((MWCharArray)inputFile);
// Extract the double value from the MWArray
double fileID = ((double[,])result.ToArray())[0, 0];
Console.WriteLine($"File ID: {fileID}");
}
catch (Exception exception)
{
Console.WriteLine("Error: {0}", exception);
}
}
#endregion
}
Above code generated the following output:
File ID: 3
3) Using MATLAB as a COM Automation server: Call a user-defined MATLAB function from a C# application using MATLAB as a COM Automation server. Please refer to its documentation here: https://www.mathworks.com/help/matlab/matlab_external/call-matlab-function-from-c-client.html
I hope my response has been helpful to you!
0 个评论
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!