0

I have used DLL Export viewer to try and find the functions that are in this DLL, I have found a list of functions and here it is:

public: int __thiscall CSTVdsDisk::GetPartitionCount(void);

the question is within in C# I am not able to call the function using either:

[DllImport("Some.dll", 
           ExactSpelling = true,
           EntryPoint = "GetPartitionCount",
           CallingConvention = CallingConvention.StdCall,
           SetLastError = true)]

or:

[DllImport("Some.dll", 
           ExactSpelling = true,
           EntryPoint = "CSTVdsDisk::GetPartitionCount",
           CallingConvention = CallingConvention.StdCall,
           SetLastError = true)]
private static extern int GetPartitionSize();

They all fail. Is there something that I am doing wrong? Can anyone help? Thanks!

torrential coding
  • 1,755
  • 2
  • 24
  • 34
Andrew Butler
  • 1,060
  • 2
  • 14
  • 31

3 Answers3

2

You can't call that function using P/Invoke. The __thiscall calling reference means that this function is a class member function. It is a member function of the CSTVdsDisk class.

To be able to call the function you will have to create an instance of the CSTVdsDisk class and call GetPartitionCount from that instance.

You'll have to do that in C++ or C++/CLR as you can't create a C++ class in C#. See also Create unmanaged c++ object in c#.

Community
  • 1
  • 1
shf301
  • 31,086
  • 2
  • 52
  • 86
1

Based on the name, that appears to be a C++ class method. That is going to make it very difficult to call that method directly from P/Invoke for two reasons:

  1. You need to find the "real" name; the Export Viewer is apparently showing up the unmangled name, but the actual C++ function name will look much uglier, like @0GetPartitionCount@CSTVdsDisk@@QPBAEXA or similar. You may need to use a lower-level tool like dumpbin to find that name.
  2. You need to fake the "thiscall" style call; this means you need to pass an instance of a C++ class as the first parameter. This is only going to work if the C++ class constructor is also exposed from the DLL; in which case, you can call the class constructor, store the result in an IntPtr, and pass it to every subsequent call. (If the constructor is exposed as a DLL export its mangled name will start with ??, like `??0CSTVdsDisk@@QAE@ABV0@@Z

This CodeProject article shows you how to do most of that, but it's pretty fragile, so expect problems. I'd strongly suggest you look for a non-C++ library that does something similar, or at least one that's designed to be usable from C code.

Michael Edenfield
  • 28,070
  • 4
  • 86
  • 117
0

In your native code, make sure you're exporting the function. By default you function wont be listed in the Exports table so you need to mark it so that the compiler knows to export it. You also need to mark the function as extern "C" so that the compiler doesn't mangle the name.

Typically I define the following macro:

#define DLLEXPORT extern "C" __declspec(dllexport)

to handle all of this, and then simply declare exported functions like:

 DLLEXPORT __cdecl int Example(int x, int y)

If you find you're still having troubles with the name, try using a free PE explorer program on the dll and checking the exported function table for the correct name.

Jason Larke
  • 5,289
  • 25
  • 28
  • I don't have the source to the DLL, I am trying to use a function from another program so I can format disks under c# – Andrew Butler Jun 21 '12 at 23:34
  • In that case, skip to the bit about using a PE explorer to get the correct exported name. You can use the trial version http://www.heaventools.com/overview.htm of "PE Explorer" for 30 days, it comes in handy. – Jason Larke Jun 21 '12 at 23:52