views:

5360

answers:

6

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 ... ?

+6  A: 

First make sure the function is actually exported:

dumpbin /exports whatever.dll

jeffamaphone
I have a line in the output which says"14 D 00007B40 ?recoCHN_P_Name@CcnOCRsdk@@QAE_NPADPAURECO_DATA@@@Z"what does that tell me?
Evgeny
See http://www.kegel.com/mangle.html for a detailed explanation of how to decrypt it. Make sure you've got the datatypes correct.
jeffamaphone
This definitely pointed me to the right direction, thanks
Evgeny
+1  A: 

This page seems to indicate that 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.

paxdiablo
+2  A: 

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.

danbystrom
+3  A: 

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.

Evgeny
This solved my problem! Thanks!
A: 

You could try using the unmangled name while specifying a CallingConvention in the DllImport

evilfred
A: 

I have written several C++ dlls which I routinely call from MFC exes. They don't contain MFC, but they do use STL, and my life is multilingual and therefore all UNICODE. I just wrote my first ASP.NET 3.5 site and I want to call my C++ dlls from my new site. I have tried several options, first with an easy call that takes an int and returns a bool. For example, I tried hard-coding the path name:

using System;

using System.Runtime.InteropServices;

public class ExternalCalls { public ExternalCalls() { }

[DllImport("Widgets.dll", EntryPoint = "is_function_word_pos", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention=CallingConvention.StdCall)]

static extern bool is_function_word_pos(int pos_num);

public bool is_function_word(int num)
{
    return is_function_word_pos(num);
}

};

Other things I have tried are:

Hard-coding the path to my App_Code directory. This resulted in a side-by-side error.

Recompiling the dll in VS2008 under a configuration called simply 'Release'. The original dll's conifguation is 'Release Multithreaded Dll".

Setting the 'unsafe' compiler switch and specifying the function as:

static unsafe extern bool is_function_word_pos(int pos_num);

Simplifying the DllImport call (not specifying the character set and calling convention.

Any clues?

Margaret
Please post this as a new question rather than an answer to another question.
Brian Cline