Wrox Programmer Forums
|
.NET Framework 3.5 For discussion of the Microsoft .NET Framework 3.5.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the .NET Framework 3.5 section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old June 8th, 2010, 02:23 PM
Authorized User
 
Join Date: Apr 2010
Posts: 19
Thanks: 17
Thanked 0 Times in 0 Posts
Default calling C++ dll

I have just written my first ASP.NET 3.5 site, and now I want to call a C++ dll from. The dll uses STL. The exported functions are in a namespace rather than a class, so you don't need to create an instance. A colleague had just managed to call a C++ dll from C# in a different context (not ASP.NET), and based on his template I created a StringTools.cs class in the App_Code folder with the following contents:

public class StringTools
{
public StringTools()
{
}

[DllImport("Widgets.dll", EntryPoint = "uc_first", SetLastError = true,
CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern string uc_first(string w);

public string UCFirst(string w)
{
return uc_first(w);
}
}


Then from a Web page, I did:

Label1.Text = UCFirst("chicken");

I put the dll in the App_Code folder alongside the StringTools.cs.

I got the error message:

Unable to load DLL 'Widgets.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)

*************
I didn't expect it to work right away, but I wonder where to go for guidance. In particular

1. Am I putting the dll in the right directory?
2. Are there issues converting to and from STL? (The dll takes an std::string)
3. Do I have to do something akin to an #include?
4. Do I have to register the dll? How do I do that?

Where do I go to find the answers to these questions?

Thanks.
 
Old June 9th, 2010, 02:23 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

The error is caused by the location of the DLL.

I would try putting it in the "bin" directory, and if that doesn't work then in the Windows/System32 directory perhaps?

Also, your class defines UCFirst as a instance method, so you would need to create an instance of the StringTools class first. Alternatively change UCFirst to be a static method and then call it like so, StringTools.UCFirst("chicken");
__________________
/- Sam Judson : Wrox Technical Editor -/

Think before you post: What have you tried?
The Following User Says Thank You to samjudson For This Useful Post:
hvete (June 9th, 2010)
 
Old June 9th, 2010, 06:56 AM
Authorized User
 
Join Date: Apr 2010
Posts: 19
Thanks: 17
Thanked 0 Times in 0 Posts
Default thanks!

I have actually created an instance of StringTools before calling UCFirst. What I meant is that inside the dll, the calls are defined inside a namespace rather than a class. Sorry for the confusion.

I couldn't find the bin directory (??), and in any case, I'm using a commercial ISP, and I doubt they're going to let me drop a bunch of random dlls in their bin directory. So I used the exact path in the [DllImport] call. Is there a system call to determine the exact path where my site is located for when I upload my site?

Now I got the error:

The application has failed to start because its side-by-side configuration is incorrect.

From hunting around the Web, I gather that side-by-side configuration has to do with the manifest. So I recompiled, except I turned embed manifest off. (I don't really know what all these compiler switches mean. Our lead programmer just tells me which to use, and I use them. However, this is a personal project.) It then generated a dll and a manifest file. I tried dropping both in the App_Code folder, and it couldn't find the dll again. So I deleted the manifest file, and it still couldn't find the dll. So I put it back the way it was, and now I have this side-by-side problem. The dll was compiled using VS 2005, and the site was created using VWD 2008. I have found that I can't run both on the same machine, because of a SQL Server incompatibility. I don't have the commercial version of VS 2008. Can I set some compiler switches in VS2005 to make the side-by-side problem go away?
 
Old June 9th, 2010, 07:34 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

The bin directory is just a directory call "bin" in the same directory as the App_Code directory. If it doesn't exist try creating it and putting the dll and manifest file in there.

Other than I'm running out of options as I haven't done this before myself.
__________________
/- Sam Judson : Wrox Technical Editor -/

Think before you post: What have you tried?
The Following User Says Thank You to samjudson For This Useful Post:
hvete (June 9th, 2010)
 
Old June 9th, 2010, 08:41 AM
Authorized User
 
Join Date: Apr 2010
Posts: 19
Thanks: 17
Thanked 0 Times in 0 Posts
Default thanks!

I get the same effect as with the absolute path solution. I'll just start experimenting with compiler switches and what not. I'll let you know if I resolve it.
 
Old June 9th, 2010, 10:54 AM
Authorized User
 
Join Date: Jan 2010
Posts: 15
Thanks: 0
Thanked 1 Time in 1 Post
Default

you need to install VC++ redistributable depending upon visual studio version. Here are the links for various versions.

VS2005
http://www.microsoft.com/downloads/d...displaylang=en

VS2005 SP1
http://www.microsoft.com/downloads/d...displaylang=en

VS2008
http://www.microsoft.com/downloads/d...displaylang=en

VS2008 SP1
http://www.microsoft.com/downloads/d...displaylang=en

Hope this helps.
Kushal
The Following User Says Thank You to kushalkg For This Useful Post:
hvete (June 9th, 2010)
 
Old June 9th, 2010, 11:30 AM
Authorized User
 
Join Date: Apr 2010
Posts: 19
Thanks: 17
Thanked 0 Times in 0 Posts
Default Great!

Very helpful. Thanks!
 
Old June 24th, 2010, 02:24 PM
Authorized User
 
Join Date: Apr 2010
Posts: 19
Thanks: 17
Thanked 0 Times in 0 Posts
Default some success!

Okay, I have managed to call my dll! I put the dll in the App_Code directory, and I call it as follows:

const string _dllLocation = "C:\\fullpath...\\mydll.dll";
[DllImport(_dllLocation, EntryPoint= "?my_function@myNamespace@@YAPA_WPA_W@Z", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention.StdCall)]
unsafe public static extern String my_function(int z);

public String callingFunction() {
return my_function(28);
}

Some things to notice:

1. You have to use the 'decorated name', which you get by running an app called Dependency (or Dependency Walker), which is put on your system when you install VS2008. You open your dll in it, and it gives you the decorated names of all its functions
2. I haven't tested all the variations on these parameters, but if you use 'unsafe' here, you have to specify an unsafe compile in the web.config:
<compiler language="c#;cs;csharp" compilerOptions="/unsafe"...>
3. There's a whole science to converting parameters. I have chosen an easy example where you don't have to "Marshal" parameters. But for any string, you pass in, you have to Marshal it. Furthermore, there is a bug with boolean return types, so these too must be marshalled.
4. I love STL, but I didn't find a way to send an STL string back or to receive one. So I had to write a wrapper which only talks in TCHAR *. In this case, what I am returning from the C++ dll is a TCHAR *. The C++ dll has to allocate this string in RAM, and it can't be doing it with a normal 'new' or 'malloc', because these strings will be allocated on C++'s own heap, and will not be visible in C# space. The C++ routine must use CoTaskMemAlloc to allocate the string. The C# Marshalling then frees the string after it copies it to a String, so there isn't a memory leak.

So that's my contribution on this subject of calling C++ dlls from C#.

However, notice that I am passing the full path to DllImport. This site is hosted, and I will not know the full path when it is deployed. Besides, they might get it in their heads to move it. If I just drop the dll in the App_Code folder, and give it the name of the dll and run the program, I get an error "specified module cannot be found". If I put the full path in, it finds it. But if I then remove everything in the path but the fn itself AFTER I have already gotten it to work with the full path, it's happy.

What I need is a way to tell DllImport to look for the dll in the App_Code folder before it despairs. Is there a system call that returns the path to the Web site? Or can you set a relative path somewhere in web.config so it will find the dll the first time around?
 
Old June 24th, 2010, 02:26 PM
Authorized User
 
Join Date: Apr 2010
Posts: 19
Thanks: 17
Thanked 0 Times in 0 Posts
Default PS

It didn't help to put the dll in a bin directory. Also, it seems happy regardless of what my C++ configuration is called.
 
Old June 24th, 2010, 04:41 PM
Authorized User
 
Join Date: Apr 2010
Posts: 19
Thanks: 17
Thanked 0 Times in 0 Posts
Default more data

I just went through all the system calls in alphabetical order, and found one that gives me the directory where my Web site resides, namely:

HttpRuntime.AppDomainAppPath

However, when I try to do the following it gives me a compile error:

const string dllLocation = HttpRuntime.AppDomainAppPath + "\\App_Code\\mydll.dll";
[DllImport(_dllLocation)]

It seems it doesn't think HttpRuntime.AppDomainAppPath is constant enough to assign. However, if I take the const away, it complains that DllImport refers to a non-static. If I try writing a routine:

String GetAppPath()
{
return HttpRuntime.AppDomainAppPath;
}

[DllImport(GetAppPath)] //or [DllImport(GetAppPath()]

it doesn't know how to parse that. Any suggestions?





Similar Threads
Thread Thread Starter Forum Replies Last Post
.Net do not use all the cpu calling to C++ DLL wakeup .NET Framework 2.0 5 January 23rd, 2008 05:29 AM
Calling a dll inside from a dll tiredcat Visual Basic 2005 Basics 2 August 30th, 2007 11:02 PM
Calling C# DLL from C virajithasarma C# 1 August 17th, 2005 04:01 AM
HOW TO - Calling an ActiveX DLL in a UserCont arvindkrishnan VB How-To 2 August 3rd, 2005 01:14 PM
Calling an ActiveX DLL in a UserControl arvindkrishnan VB Components 4 February 9th, 2004 03:38 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.