I am having some strange problem. I have written a small module in VC++ using OpenCV.
It works fine. The code aggregates feed from the CCTV camera connected to the USB port.
however, I had to write the rest of my application in C#, so I made a DLL of the VC++ code and called the VC++ method from C#.
Now, I have ended up getting an error
Attempted to read or write protected memory.
This is often an indication that other memory is corrupt.
Can anyone please suggest me any solution to this. Is there any Access Violation while accessing it in a managed code?
If TrackBlob returns a string, you should be able to define your dllimport as such:
[DllImport("Tracking.dll", EntryPoint = "TrackIt")]
public extern static string TrackBlob();
and skip trying to marshal it.
By returning it as an IntPtr, you're trying to get a pointer into memory owned by the unmanaged DLL... returning it as a string will return a copy of the string for you to work with.
Let me know if that works!
James
* Edit *
Try one of these:
[DllImport("Tracking.dll", EntryPoint = "TrackIt")]
public extern static [MarshalAs(UnmanagedType.BStr)] string TrackBlob();
or
[DllImport("Tracking.dll", EntryPoint = "TrackIt")]
public extern static [MarshalAs(UnmanagedType.AnsiBStr)] string TrackBlob();
Check out this MSDN link on string marshalling:
http://msdn.microsoft.com/en-us/library/s9ts558h.aspx
Related
I am trying to wrap the public API in a DLL file for the STMCubeProgrammer in C#. There is header file, documentation, and some C++ examples provided for the library.
The examples projects works well, so I can connect, read, write the target with them.
When I try to wrap the first function which is used in the example from the DLL, and I try to call it from C# simply just nothing happens.
This is the example code (important part):
debugConnectParameters *stLinkList;
int getStlinkListNb = getStLinkList(&stLinkList, 0);
This is from the header file for the DLL:
int getStLinkList(debugConnectParameters** stLinkList, int shared);
With this I get for getStlinkListNb = 1 as 1 STLink is connected
Here is the C# Dll import part:
[DllImport(#"C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer\api\lib\CubeProgrammer_API.dll")]
public static extern int getStLinkList(ref IntPtr stLinkList, int shared);
And here is my code in my test method:
IntPtr list = IntPtr.Zero;
var count = CubeProgrammerAPI.getStLinkList(ref list ,0);
But nothing happens, count is zero, list is zero, there is no error. I tried different verisons like this with ref, also out, used the In, Out attributes in the method prototype.
I tried with unsafe and pointers:
[DllImport(#"C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer\api\lib\CubeProgrammer_API.dll")]
public static unsafe extern int getStLinkList(debugConnectParameters** stLinkList, int shared);
CubeProgrammerAPI.debugConnectParameters *dbgParams;
var count = CubeProgrammerAPI.getStLinkList(&dbgParams, 0);
But nothing again
I tried with safe code also, ref array of the struct itself, but nothing happens, no error.
Can somebody help me? Is it normal, that I do not get any error but it is not working either?
Thanks for the help!
Okay I found the problem on an other topic. It is not interop related but related to the DLL I wanted to wrap (mostly).
This is the solution: https://stackoverflow.com/a/62924001/6330997
I need to retrieve package information in my C# application running on Linux.
I've tried to use Python.NET which wrap python-apt which wrap libapt-pkg.so, and it works but I would prefer to go more direct by pinvoke libapt-pkg.
But I need help on my DLLImport statement.
When using python-apt I first initialize the apt module, then instantiat the Cache() class and then called the Cache.keys() function which retrieve all package-names as a string array.
If I can get this to work using pinvoke I believe I have a good chance getting the rest working too (retrieve the more advanced stuff)
Just to show some code which doesn't work, but just to get started:
[DllImport("libapt-pkg")]
public static extern dynamic GetPkgCache();
dynamic AptCache = GetPkgCache();
I get the error:
System.Runtime.InteropServices.MarshalDirectiveException: 'Cannot
marshal 'return value': Invalid managed/unmanaged type combination
(Marshaling to and from COM VARIANTs isn't supported).'
I've been looking in the header file cachefile.h of the apt project. Maybe these lines are useable for my DllImport statement?
..
inline operator pkgCache &() const {return *Cache;};
inline operator pkgCache *() const {return Cache;};
..
inline pkgCache* GetPkgCache() { BuildCaches(NULL, false); return Cache; };
..
But I'm new to C/C++ so it doesn't make much sense for me at present.
UPDATE:
Thanks for the feedback.
[DllImport("libapt-pkg")]
public static extern IntPtr GetPkgCache();
Now I get the error
System.EntryPointNotFoundException: 'Unable to find an entry point
named 'GetPkgCache' in shared library 'libapt-pkg'.'
Background: Trying to use GhostScript to convert PCL to Tiff. I am getting this error when trying to convert PCL to Tiff in a c# winforms application.
I am using Matthew's sample from https://github.com/mephraim/ghostscriptsharp.
This a cool wrapper that gives me access to the GS API.
But getting this error for some reason result is < 0:
Do I need to install GS on my computer? The sample already came with gsdll32.dll and gsdll64.dll. I am trying to convert PCLToTiff. The sample has gsdll64 and does not include gpcl6dll6.dll.
Could this be the problem? Does gsdll64 encompass everything including PCL?
Here are the args.
I also tried it without the wrapper just by calling the executable. No luck yet.
I have the executable gs9533w32.exe at C:\Users\tom\Desktop\GhostLib\gs9533w32.exe.
I also have newForm.PCl in the bin Debug folder of the application.
I also tried using gpcl6win64.exe
Next trial:
Next question: If I were to buy a license for GhostPCL and integrate it as a part of the solution we provide, how would the install work? Is it as simple as putting the exe and DLL in a folder and just calling it from there or is there some installation involved?
I figured it out. I just had to do a DLLImport for gpcl6dll6. The wrapper sample didn't have gpcl6dll6. It only had gsdll's
[DllImport("gpcl6dll32.dll", EntryPoint = "gsapi_new_instance")]
private static extern int CreateAPIInstance(out IntPtr pinstance, IntPtr caller_handle);
[DllImport("gpcl6dll32.dll", EntryPoint = "gsapi_init_with_args")]
private static extern int InitAPI(IntPtr instance, int argc, string[] argv);
[DllImport("gpcl6dll32.dll", EntryPoint = "gsapi_exit")]
private static extern int ExitAPI(IntPtr instance);
[DllImport("gpcl6dll32.dll", EntryPoint = "gsapi_delete_instance")]
private static extern void DeleteAPIInstance(IntPtr instance);
#endregion
I am using VS 2008 C#
Windows Application.
I have this DLL Import I am trying to use.
[DllImport("Mapi32.dll", PreserveSig = true)]
private static extern void
WrapCompressedRTFStream(
[MarshalAs(UnmanagedType.Interface)]
UCOMIStream lpCompressedRTFStream,
uint ulflags,
[MarshalAs(UnmanagedType.Interface)]
out UCOMIStream lpUncompressedRTFStream
);
public const uint MAPI_MODIFY = 0x00000001;
public const uint STORE_UNCOMPRESSED_RTF = 0x00008000;
I have a compressed string that is in CompressedRFTFormat.
How do I pass the string into the WrapCompressedRTFStream? I do not understand what the method is expecting.
I am trying to use it on a button.
RichText1.text = WrapCompressedRTFStream(_CompressedRichText.ToString(),something,somethingelse);
The first error I get is "cannot convert from 'string' to 'System.Runtime.InteropServices.UCOMIStream"
I hope someone who understands this posts an answer that helps!
ok, so I end up in the same situation when I use the IStream.
[DllImport("Msmapi32.dll", PreserveSig = true)]
private static extern void WrapCompressedRTFStream(
[MarshalAs(UnmanagedType.Interface)]
IStream lpCompressedRTFStream,
uint ulflags,
[MarshalAs(UnmanagedType.Interface)]
out IStream lpUncompressedRTFStream
);
The real issue here is I do not understand what / how to deal with the input and output of this method.
I suppose it's not a good idea to use legacy native-code libraries & I would investigate some more time to find analogous code in .net
Try out com interop or p-invoke .net technologies to use legacy code.
If you can't find a native .NET method for doing this, a good approach would be to contain your approach in a Managed C++ wrapper.
What this will let you do is create C++ code to perform your work, while exposing a managed class to call the method. This may be more complicated since it will require you to learn Managed C++, but allows you to do any C++ work necessary, returning a .NET string containing your "answer".
UCOMIStream is deprecated, use ComTypes.Istream instead. Then look at System.Runtime.InteropServices.ComTypes.IStream to System.IO.Stream
I have a dll which comes from a third party, which was written in C++.
Here is some information that comes from the dll documentation:
//start documentation
RECO_DATA{
wchar_t Surname[200];
wchar_t Firstname[200];
}
Description:
Data structure for receiving the function result. All function result will be
stored as Unicode (UTF-8).
Method:
bool recoCHN_P_Name(char *imgPath,RECO_DATA *o_data);
Input:
char * imgPath
the full path of the image location for this
function to recognize
RECO_DATA * o_data
data object for receiving the function
result.
Function return:
True if Success, otherwise false will return.
//end documentation
I am trying to call the recoCHN_P_Name from my C# application. To this end, I came up with this code:
The code to import the dll:
public class cnOCRsdk
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct RECO_DATA{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=200)]
public string FirstName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 200)]
public string Surname;
}
[DllImport(#"cnOCRsdk.dll", EntryPoint="recoCHN_P_Name")]
public static extern bool recoCHN_P_Name(byte[] imgPath, RECO_DATA o_data);
}
The code to call the function:
cnOCRsdk.RECO_DATA recoData = new cnOCRsdk.RECO_DATA();
string path = #"C:\WINDOWS\twain_32\twainrgb.bmp";
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
byte[] bytes = encoding.GetBytes(path);
bool res = cnOCRsdk.recoCHN_P_Name(bytes, recoData);
And the error I'm getting is
""Unable to find an entry point named 'recoCHN_P_Name' in DLL 'cnOCRsdk.dll'."
I'm suspecting that I'm having an error in converting a type from C++ to C#. But where exactly ... ?
First make sure the function is actually exported:
In the Visual Studio Command Prompt, use dumpbin /exports whatever.dll
C# doesn't support C++ name mangling and you either need to declare the C++ functions with
extern "C" {...}
(may not an option if they're from a third party), or call the mangled name directly if you can get it to work. It may be easier to get the third party to provide a non-mangled interface to the functionality.
Solved - at least to the point where the program does not break and actually returns me a bool value.
The key, I guess, was to specify the entry point as the 'mangled' name
[DllImport(#"cnOCRsdk.dll", EntryPoint="?recoCHN_P_Name#CcnOCRsdk##QAE_NPADPAURECO_DATA###Z")]
public static extern bool recoCHN_P_Name(ref string imgPath, ref RECO_DATA o_data);
After that I got some other errors but the 'unable to find entry point' went away.
I solved the same problem in these steps:
step 1) If you program your custom DLL in C++ using Visual studio,then at the property page of your project set the Common Language Runtime Support (/clr)parameter to Common Language Runtime Support (/clr).
step 2) To function deceleration in .h file use __declspec(dllexport) keyword like below:
__declspec(dllexport) double Sum(int a,int b);
step 3) Build and export DLL file, then use the Dependency Walker software to get your function EntryPoint.
step4) Import DLL file In the C# project and set EntryPoint and CallingConvention variable like below:
[DllImport("custom.dll", EntryPoint = "?Sum##YAXHHHHHHNNN#Z", CallingConvention = CallingConvention.Cdecl)]
public static extern double Sum(int a,int b);
I'd write a wrapper using C++/CLI. This wrapper will be able to include the .h files and link to the .lib files you got from the third party vendor. Then it is both easy and safe to write a managed interface for your C# program.
Correct EntryPoint string could be found in ".lib" file that comes along with main unmanaged dll.
We had this problem when we want to access to DB and solved it by changing EF core to EF 6.4.4
It may be you have a problem like this and need to change or downgrade your version of EF (If you used EF)
We had this problem .we change EntityFramework.core to EntityFrameWork 6.4.4 and after that the program worked fine. you most change you're Framework Version.
you may get this error due to string marshalling mismatch between DLL and your application . for example, one is using ANSI and the other is unicode.
you can try something like this:
[DllImport("yourDLL.dll", CharSet = CharSet.Unicode )]
public static extern String YourFunction(String name);
checkout HERE for a list of other possible reasons.
You could try using the unmangled name while specifying a CallingConvention in the DllImport