views:

65

answers:

3

The explanation of the problem is a little long-winded, please bear with me.

I have an unmanaged C++ static library that is used for financial application. It has business day conventions, swap conventions, bond conventions, etc. Most of the conventions rely on static global variables, which are initialized on first use. The library also initializes the holiday calendars on startup by running some queries against a SQL Server database using ODBC.

I have to interact with third-party software using web services. The only way to do this realistically is through C#. That isn't an issue, and I was making good progress. However, I hit a stumbling block when it became necessary to do some date calculations in C#. Since I didn't want to port all my C++ code to C#, I figured the most efficient way to achieve this would be by writing a Managed C++ Class Library DLL that is a wrapper around my unmanaged static library. Everything seems to work fine, I get no compile-time or link-time errors, and I can add the reference to the wrapper and see all the proper object definitions. However, when I try to run my application, it just hangs. I have tried playing around with a bunch of compiler setting for the wrapper DLL, to no avail. If I remove the project dependency on my unmanaged library, everything works fine. I have a strong suspicion that my liberal use of global static variables is causing issues. Is there are way to solve this problem, are at least figure out where the issue is? Example code is below.

Thanks, Marc.

// FSAManaged.h

#pragma once

using namespace System;

//class XLDate;

namespace FSAManaged {
 public ref class Futures
 {
 public:
  static DateTime Expiry(String ^ code, DateTime date);
 };
}

The implementation does not even rely on a dependency to the unmanaged static library:

// This is the main DLL file.
#include "stdafx.h"
#include "FSAManaged.h"


namespace FSAManaged
{
 DateTime Futures::Expiry(String ^ code, DateTime date) {
  return DateTime::Today;
 }
}

For completeness' sake, here is AssemblyInfo.cpp:

#include "stdafx.h"

using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;

//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly:AssemblyTitleAttribute("FSAManaged")];
[assembly:AssemblyDescriptionAttribute("")];
[assembly:AssemblyConfigurationAttribute("")];
[assembly:AssemblyCompanyAttribute("?????")];
[assembly:AssemblyProductAttribute("FSAManaged")];
[assembly:AssemblyCopyrightAttribute("??????")];
[assembly:AssemblyTrademarkAttribute("")];
[assembly:AssemblyCultureAttribute("")];

//
// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
// You can specify all the value or you can default the Revision and Build Numbers
// by using the '*' as shown below:

[assembly:AssemblyVersionAttribute("1.0.*")];

[assembly:ComVisible(false)];

[assembly:CLSCompliantAttribute(true)];

[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
+1  A: 

Use the debugger. If you test this from C# then Project + Properties, Debug, tick "Enabled unmanaged code debugging". Setting up the symbol server in Tools + Options, Debugging, Symbols is strongly recommended. Run.

When it hangs use Debug + Break All. Debug + Windows + Threads and double-click the thread that is supposed to be doing the job. Debug + Windows + Call stack to see what is going on. Post the stack trace in your question if you can't figure it out. Anything you see in the Output window and the Visual Studio status bar is relevant too.

Hans Passant
A few notes: (I) There is no "Enable unmanaged code debugging", only "Enable the Visual Studio hosting process" (II) I am testing it with a console app, I think that explains why I don't see Debug + Windows + Threads (III) The only thing the call stack shows is "External Code"
Hazerider
I have no clue what kind of version of Visual Studio you are using to *not* have this option. When options that have been around for over 5 years are missing, the burden is on you to document your question better. Just in case it is relevant: high time to upgrade to the paid version of Visual Studio when you have a problem like this.
Hans Passant
I am using Visual Studio Express 2008.
Hazerider
Yes, I figured. High time.
Hans Passant
A: 

Make sure not to initialize any variables at the global scope or you might have initialization errors that can't be debugged into.

iterationx
A: 

Static C++ variables are initialized from DllMain. There are lot's of things you should not do in DllMain; triggering the load of yet another Dll being the most important one. This is easy to break if you call into other peoples libraries in from DllMain.

I suggest you make an Init function on your Dll, which you call after the dll is up and running.

jdv
This is a static library. I thought there was no DllMain?
Hazerider
Oh, yeah you wrote so. In that case ... this may not apply. In general though, it is asking for trouble to do complex stuf in static variable initialization.
jdv