2

I'm using VS2012 and trying to call a function in a C# project from a C DLL I've written. The C DLL is called by an external app (Thunderbird).

I've found the Unmanaged Exports page and followed the instructions. In the process, my C# project had to be set to .net4 and x86 to get everything to compile and link as far as it does. But I have a linker error I can't resolve, and since this is uncharted territory for me it may be I'm just doing something stupid.

In my C# I have;

 using RGiesecke.DllExport;

 namespace StreamAttacher
 {
     class Test
     {
         [DllExport("add", CallingConvention = CallingConvention.Cdecl)]
         public static int TestExport(int left, int right)
         {
             return left + right;
         }
     }
 }

And in my C I have

 #include<stdio.h>

 int add(int left, int right); //in c#

 __declspec(dllexport)char* strTest2()
 {
    int i = add(2,3);
    char *p = "C:\\Work\\Mozilla\\Test dir\\testfile.zip";
    return p;
 }

The C project references the C# project in its external dependencies.

On building, I get the linker error "error LNK2019: unresolved external symbol _add referenced in function _strTest2"

If I look at the C# DLL using DllExp then I see nothing exported. Should I? I was expecting to see the "add" function but it's not there, and nor are any errors generated when I build the C# DLL on its own.

Also, is that proto for 'add' in the C code all I need if things are working right further back along the chain?

Craig Graham
  • 1,161
  • 11
  • 35
  • 1
    You need an import library for the DLL to keep the linker happy. You don't have one and you can't get one from that utility. Writing a .def file and converting it to an import library is technically possible, albeit very error prone. This just isn't very practical for real applications. Use the [unhacky way](http://stackoverflow.com/a/2082212/17034). – Hans Passant Dec 03 '13 at 16:51

2 Answers2

1

I recently tried exporting C# functions for the same purpose (using RGiesecke's library and other methods), couldn't get it to work and found it to be very hairy. If you have the option to try something else, I would suggest looking into writing a C++/CLI library as an intermediate instead. To me, it is a much more interopable solution.

Here is a decent tutorial: http://www.codeproject.com/Articles/19354/Quick-C-CLI-Learn-C-CLI-in-less-than-10-minutes

Miles Watson
  • 169
  • 1
  • 8
0

You may want to define your c# signatures using marshalling attributes for your string parameters.

[DllImport(@"c:\GDAit.dll")]
public static extern long TransGeogPt([MarshalAs(UnmanagedType.LPStr)] string sGridFile, long lDirection, double dLat, double dLong, ref double pdLatNew, ref double pdLongNew, ref double pdLatAcc, ref double pdLongAcc);

[DllImport(@"c:\GDAit.dll")]
public static extern long TransProjPt([MarshalAs(UnmanagedType.LPStr)] string sGridFile, long lDirection, double dLat, double dLong, long lZone, ref double pdLatNew, ref double pdLongNew, ref double pdLatAcc, ref double pdLongAcc);

I'll also piggy-back on Mark Sowul's answer and say try calling with StdCall instead of Cdecl.

Also, as a precaution, I'd probably double-check to make sure that the compiler is set to compile x86 code, in case its compiling for 64-bit.

Shell
  • 6,818
  • 11
  • 39
  • 70