Adding functions to an existing Objective-C class raises error - c++

I'm writing a C++ wrapper for the NSImage class and I'm having trouble with the additional functions that I wrote. Here's brief summary:
NSImageExtras.h
#interface NSImage (MyExtensions)
-(NSString*) myExtraFunction;
#end
NSImageExtras.mm
#import "NSImageExtras.h"
#implementation NSImage (MyExtensions)
-(NSString*) myExtraFunction
{
return #"Hello World";
}
#end
NSImageWrapper.h
class NSImageWrapper
{
public:
// nsImage is of type (NSImage*)
NSImageWrapper(void* nsImage) {myImage = nsImage;}
~NSImageWrapper() {}
CFStringRef myExtraFunction();
// Cast this into (NSImage*)
void* getNSImage() {return myImage;}
private:
void* myImage;
};
NSImageWrapper.mm
#include "NSImageWrapper.h"
#import "NSImageExtras.h"
CFStringRef NSImageWrapper::myExtraFunction()
{
return (CFStringRef) [(NSImage*) myImage myExtraFunction];
}
This compiles. But when I try to call myExtraFunction an error is raised because the function isn't found. If I change the import "NSImageExtra.h" into import "NSImageExtra.m" then it works, but I'd rather avoid adding .m files in my imports.
Any idea why this is happening?
Thanks ahead.

You can try to import NSImageExtras.h in NSImageWrapper.h instead of NSImageWrapper.mm. You need to include subclass headers in the header files.

Related

EXC_BAD_ACCESS Xcode from my c++ wrapper in objective-c++ and swift bridging header

I'm working on a app using openCV and a utility class "Detector" created in C++. I want to create a objective-c++ wrapper "DetectorWrapper" for the c++ class and use this wrapper in Swift (bridging header). But know when I try to call a fonction from DetectorWrapper, my app crash with the error : EXC_BAD_ACCESS
I read sowewhere that to be allow to use the objective-c++ class in Swift, I cannot include c++ file in the DetectorWrapper.h so I use the type id.
Here is my c++ class: "Detector.h"
#include "opencv2/opencv.hpp"
class Detector
{
public:
// Constructor
Detector(int inputPlayerIdx);
// Scan the input video frame
void scanFrame(cv::Mat frame);
// Tracking API
bool isTracking();
};
My wrapper: "DetectorWrapper.h"
#interface DetectorWrapper : NSObject
#end
#interface DetectorWrapper ()
#property (nonatomic, readwrite, assign) id bld;
- (id)init: (int) inputPlayerIdx;
- (void)dealloc;
- (void) scanFrame: (UIImage*) frame;
- (bool) isTracking;
#end
"DetectorWrapper.mm"
#import "DetectorWrapper.h"
#import "Detector.hpp"
#import "UIImage+OpenCV.h"
#implementation DetectorWrapper
#synthesize bld = _bld;
- (id)init: (int) inputPlayerIdx {
self = [super init];
if (self) {
_bld = (__bridge id) new Detector(inputPlayerIdx);
}
return self;
}
- (void)dealloc {
//[self->_bld dealloc];
//[super dealloc];
//delete _bld;
}
- (void) scanFrame: (UIImage*) frame{
[self->_bld scanFrame:frame];
}
- (bool) isTracking{
return [self->_bld isTracking];
}
#end
Using this in Swift:
let detector = DetectorWrapper(2)
detector.isTracking()
with the file "Detector.h" in Bridging Header.
I got the "EXC_BAD_ACCESS" error when calling for .isTracking
I don't understand the problem at all and how to figure it out.
Maybe I just made a mistake coding my objective-c++ wrapper, I'm not used to this language. Any ideas?
One problem here is that a C++ object is used as if it was an Objective-C object, and these kinds of objects are not interchangeable.
For illustration purposes and for simplicity, let's eliminate the scanFrame method. Then DetectorWrapper.h becomes
#interface DetectorWrapper : NSObject
- (id)init: (int) inputPlayerIdx;
- (void)dealloc;
- (bool) isTracking;
#end
and the wrapper implementation:
#implementation DetectorWrapper
{
// Instance variable to hold a C++ object pointer
Detector * ptrDetector;
}
- (id)init: (int) inputPlayerIdx {
self = [super init];
if (self) {
ptrDetector = new Detector(inputPlayerIdx);
}
return self;
}
- (void)dealloc {
// Don't want to leak the C++ Detector instance
delete ptrDetector;
}
- (bool) isTracking{
return ptrDetector->isTracking();
}
#end
Please note that when you re-introduce scanFrame, you won't be able to just pass UIImage* to ptrDetector->scanFrame(), which takes cv::Mat, you'll have to do some magic in your wrapper's scanFrame to convert between the 2 types, but that's a topic in its own right, I think. BTW, I'm assuming that in your example Detector.h and Detector.hpp refer to the same file, it's just a typo.

new in Objective-C in init - how to handle std::bad_alloc?

I need to wrap a c++ object inside an Objective-C class - initially I did that by putting the C++ objects inside the #implementation in the .mm file like this:
MyObjCClass.h:
#interface MyObjCClass : NSObject
#end
MyObjCClass.mm:
#implementation MyObjCClass {
MyCppClass member;
}
#end
Sadly I had to give this up since this code is also used in a project which targets 32-bit architectures and thus this feature is not supported. So I did a forward struct declaration, the struct is defined in the .mm file and wraps the C++ object:
MyObjCClass.h:
struct MyObjCClassPrivate;
#interface MyObjCClass : NSObject {
MyObjCClassPrivate* memberPrivate;
}
-(void)dealloc;
-(id)init;
#end
MyObjCClass.mm:
struct MyObjCClassPrivate {
MyCppClass member;
}
#implementation MyObjCClass
-(void)dealloc
{
delete memberPrivate;
memberPrivate = nullptr;
}
-(id)init
{
if (self = [super init])
{
memberPrivate = new MyObjCClassPrivate; // what happens if new throws std::bad_alloc ?
}
return self;
}
#end
The question is - should I care if the allocation with new fails? What are the consequences (apart from the exception being thrown?) - do I need to do some additional cleanup for the Ojbective-C class instance?
I dont want to put the c++ stuff in the header since this class is also used by plain Objective-C code, which then fails to compile.

I need help mixing C++ code and Objective-C code

I am writing a device driver for a Blackmagic Design AV device in XCode, and I'm having trouble including BMD's SyncController class from their abbreviated sample code (below) into my purely Objective-C project.
Their DecklinkAPI.h file is rich in C++ code, so when I try include this header file as-is in a an Objective-C class, the compiler chokes deep in the API include: Unknown type name 'class'; did you mean 'Class'?
I have tried to to bundle up the C++ bits into a Obj-C class extension as noted here, but without much success. I've never done any C++ programming (and have never used Obj-C class extensions), so this is new territory for me.
I'm not sure if I need to create an additional wrapper class for my SyncController object, or whether I can just do a class extension on this one and shuffle the C++ bits into the .mm file.
I would like to be able to do a #include "SyncController.h" (or its wrapper) in an Objective-C class without having the compiler choke.
Any assistance in doing so would be much appreciated.
First up, here is my current SyncController.h file:
#import <Cocoa/Cocoa.h>
#import "DeckLinkAPI.h" // this is rich in C++ code
class PlaybackDelegate;
#interface SyncController : NSObject {
PlaybackDelegate* playerDelegate;
IDeckLink* deckLink;
IDeckLinkOutput* deckLinkOutput;
}
- (void)scheduleNextFrame:(BOOL)prerolling;
- (void)writeNextAudioSamples;
#end
class PlaybackDelegate : public IDeckLinkVideoOutputCallback, public IDeckLinkAudioOutputCallback
{
SyncController* mController;
IDeckLinkOutput* mDeckLinkOutput;
public:
PlaybackDelegate (SyncController* owner, IDeckLinkOutput* deckLinkOutput);
// IUnknown needs only a dummy implementation
virtual HRESULT QueryInterface (REFIID iid, LPVOID *ppv) {return E_NOINTERFACE;}
virtual ULONG AddRef () {return 1;}
virtual ULONG Release () {return 1;}
virtual HRESULT ScheduledFrameCompleted (IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult result);
virtual HRESULT ScheduledPlaybackHasStopped ();
virtual HRESULT RenderAudioSamples (bool preroll);
};
void ScheduleNextVideoFrame (void);
Next up, here is my (simplified) SyncController.mm file:
#import <CoreFoundation/CFString.h>
#import "SyncController.h"
#implementation SyncController
- (instancetype)init
{
self = [super init];
return self;
}
- (void)dealloc
{
}
- (void)scheduleNextFrame:(BOOL)prerolling
{
}
- (void)writeNextAudioSamples
{
}
#end
PlaybackDelegate::PlaybackDelegate (SyncController* owner, IDeckLinkOutput* deckLinkOutput)
{
mController = owner;
mDeckLinkOutput = deckLinkOutput;
}
HRESULT PlaybackDelegate::ScheduledFrameCompleted (IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult result)
{
[mController scheduleNextFrame:NO];
return S_OK;
}
HRESULT PlaybackDelegate::ScheduledPlaybackHasStopped ()
{
return S_OK;
}
HRESULT PlaybackDelegate::RenderAudioSamples (bool preroll)
{
[mController writeNextAudioSamples];
if (preroll)
mDeckLinkOutput->StartScheduledPlayback(0, 100, 1.0);
return S_OK;
}
I have tried to to bundle up the C++ bits into a Obj-C class extension as noted here, but without much success.
If you're targeting 64-bit, the class extension method should be fairly simple.
The following is equivalent to the code you've post, but moves all of the C++ declarations to a separate header:
SyncController.h:
#import <Cocoa/Cocoa.h>
#interface SyncController : NSObject
- (void)scheduleNextFrame:(BOOL)prerolling;
- (void)writeNextAudioSamples;
#end
SyncController_CPP.h
#import "SyncController.h"
#include "DeckLinkAPI.h"
class PlaybackDelegate;
#interface SyncController() {
PlaybackDelegate* playerDelegate;
IDeckLink* deckLink;
IDeckLinkOutput* deckLinkOutput;
}
#end
class PlaybackDelegate ...
{
...
}
SyncController.mm
#import "SyncController_CPP.h"
#implementation SyncController
...
#end
PlaybackDelegate::PlaybackDelegate (SyncController* owner, IDeckLinkOutput* deckLinkOutput)
{
mController = owner;
mDeckLinkOutput = deckLinkOutput;
}
// etc..
Any other ObjC classes that need access to SyncController will import "SyncController.h". Any other ObjC++ classes can import either "SyncController.h" or "SyncController_CPP.h"
Not a complete answer, however errors like:
Unknown type name 'class'; did you mean 'Class'?
Is a classic issue with Objective-C++ where an Objective-C implementation file is seeing a C++ header file.
I can only provide advice about how to avoid it as you didn't post the complete build output.
Don't put C++ headers is the pre-compiled header.
Try to only include C++ headers within Objective-C++ implementation files and not in their counterpart header file which might, in turn, be included into an Objective-C file.
Hide the use of C++ from any header files, for example using private instance variables:
#import <vector>
#implementation MyObjCppClass {
std::vector<int> _stuff;
}
- (id)init {
...
}
#end
If you are mixing Objective-C and Objective-C++ then you might find you need to provide Objective-C wrappers to C++ classes (which look from the outside as Objective-C but are actually implemented in Objective-C++).
Rename your .m files (objective-c) to .mm (objective-c++). this should allow you to then mix objc and c++ by including c++ headers and referencing c++ code from your objc.
---EDIT---
Any header file you include from objective-c must contain only objective-c. Remove any c++ from the header in your wrapper class to get the other objc classes to build. In modern objc, you can split your ivars between the .h and .m files; keep all your methods in the .h for other objc classes to use, and declare your c++ ivars in the .mm. Stick your c++ delegate class in its own .h that is only included from the .mm wrapper.
Use #if __cplusplus.
For example,
#import <Cocoa/Cocoa.h>
#if __cplusplus
#import "DeckLinkAPI.h" // this is rich in C++ code
#endif // __cplusplus
#interface SyncController : NSObject {
void* playerDelegate; // should be cast as C++ PlaybackDelegate class.
...
}
#end
#if __cplusplus
class PlaybackDelegate : public IDeckLinkVideoOutputCallback, public IDeckLinkAudioOutputCallback
{
...
};
#endif // __cplusplus
The header file can be used with Objective-C and Objective-C++. But you can not use C++ class signature in SyncController Objective-C class declaration in the header. Use void * instead of PlaybackDelegate * with proper type cast.
Also using void * means that C++ stuff in the header is no longer needed.
#import <Cocoa/Cocoa.h>
#interface SyncController : NSObject {
void* playerDelegate; // should be cast as C++ PlaybackDelegate class.
...
}
#end
In Objective-C++ code,
// initialize
syncController.playerDelegate = new PlaybackDelegate();
// use the pointer
PlaybackDelegate *playbackDelegate = (PlaybackDelegate *)syncController.playerDelegate;
initialize
syncController.playerDelegate = new PlaybackDelegate();
// use the pointer
PlaybackDelegate *playbackDelegate = (PlaybackDelegate *)syncController.playerDelegate

Calling C++ from Objective-C

For those of you who have successfully been able to call C++ code from Objective-C, will you please enlighten me?
This link says you need to wrap your C++ code using a technique he describes in his article. It looks good but I still have problems.
This link says that as long as the Objective-C class calling the C++ class has been converted to a .mm (Objective-C++) class then the two should work nicely together.
Each of these approaches are causing me grief the minute I try to add a method call. Can somebody please give me code for a simple Hello World iOS app that uses Objective-C for the "Hello" part and a C++ class for the "World" part with an Objective-C++ class in the middle? Or do I still have the entire concept wrong?
Essentially you need an ObjC class with .mm extension that calls an ObjC class with .mm extension. The second one will be used as a C++ wrapper class. The wrapper class will call your actual .cpp class. It's a little tricky, so I'm going to give you some verbose code. Here is an overview of the project:
In your ObjC code (ViewController) you would call the CplusplusMMClass
- (IBAction)buttonPushed:(UIButton *)sender {
self.mmclass = [[CplusplusMMClass alloc]init]; // bad practice; but showing code
NSString *str = [self.mmclass fetchStringFromCplusplus];
[self populateLabel:str];
}
Here is the CplusplusMMClass .h and .mm
#import <Foundation/Foundation.h>
#import "WrapperClass.h"
#interface CplusplusMMClass : NSObject
#end
#interface CplusplusMMClass()
#property (nonatomic, strong) WrapperClass *wrapper;
- (NSString*)fetchStringFromCplusplus;
#end
#import "CplusplusMMClass.h"
#import "WrapperClass.h"
#implementation CplusplusMMClass
- (NSString*)fetchStringFromCplusplus {
self.wrapper = [[WrapperClass alloc] init];
NSString * result = [self.wrapper getHelloString];
return result;
}
#end
Here is WrapperClass .h and .mm
#ifndef HEADERFILE_H
#define HEADERFILE_H
#import <Foundation/Foundation.h>
#if __cplusplus
#include "PureCplusplusClass.h"
#interface WrapperClass : NSObject
#end
#interface WrapperClass ()
- (NSString *)getHelloString;
#end
#endif
#endif
#import "WrapperClass.h"
#include "WrapperClass.h"
#include "PureCplusplusClass.h"
using namespace test;
#interface WrapperClass ()
#property (nonatomic) HelloTest helloTest;
#end
#implementation WrapperClass
- (NSString *)getHelloString {
self.helloTest = *(new HelloTest);
std::string str = self.helloTest.getHelloString();
NSString* result = [[NSString alloc] initWithUTF8String:str.c_str()];
return result;
}
#end
Here is the PureCplusplusClass .h and .cpp
#ifndef __HelloWorld__PureCplusplusClass__
#define __HelloWorld__PureCplusplusClass__
#include <stdio.h>
#include <string>
using namespace std;
namespace test {
class HelloTest
{
public:
std::string getHelloString();
};
}
#endif /* defined(__HelloWorld__PureCplusplusClass__) */
#include <stdio.h>
#include <string>
std::string test::HelloTest::getHelloString() {
std::string outString = "Hello World";
return outString;
}
This code is not perfect! I'm having trouble with the namespace test being recognized. I'll update when I can.
But this should get you there!!!!
Another (contrived) one:
Use a C++ class as an ivar:
File Foo.h
#import <Foundation/Foundation.h>
#interface Foo : NSObject
#property (nonatomic, readonly) NSString* what;
#end
File: Foo.mm
#import "Foo.h"
#include <string>
#implementation Foo {
std::string _string; // C++ class must have a default c-tor
}
- (id)init
{
self = [super init];
if (self) {
_string = "Hello, World!"
}
return self;
}
- (NSString*) what {
NSString* result = [[NSString alloc] initWithBytes:_string.data()
length:_string.size()
encoding:NSUTF8StringEncoding];
return result;
}
#end
Note:
An executable may need to explicitly link against the C++ library, e.g. by adding an additional flag to "Other Linker Flags": -lc++
Alternatively, the main.m file can be renamed to main.mm.
The latter is more robust in selecting the "correct" library, since the tool chain will do that itself. But perhaps, for anyone else examining the project, a renamed "main.m" may not be that obvious and may cause confusion.
I ran into this situation with xcode 12.4, needing to use an existing C++ class "CppModule" in an objective-c project. Here is what I did.
First problem was that #include in CppModule.hpp gave a compiler error: 'string' file not found. Fixed that by wrapping the .hpp file contents in
#if defined __cplusplus
declarations
#endif
Then string var declarations gave another compiler error: Unknown type name 'string'; did you mean 'std::string'? Fixed that by:
#include <string>
using namespace std;
The C++ CppModule.cpp, the CppModule.hpp include file, the calling objective-c module.m, and it's module.h files MUST all be set as Type "Objective-C++ Source", using xcode's Inspector (top right in the editor window). Renaming module.m to module.mm also sets the type to "Objective-C++ Source" (xcode 12.4). Perhaps good to use .mm, as a reminder it calls C++.
In the module.h file include the C++ header:
#include < CppModule.hpp>
Odd (to me) is that in the module.h file "CppModule" is not recognised as a known type, so you cannot declare vars or properties of that type in your module.h, but in the module.m(m) file it is a known type. In the module.mm file, after the #implementation add:
static CppModule *module_cpp;
Now you can, e.g. in the module.mm's init, call the C++ module's initialiser, like:
module_cpp = new CppModule(parameters);
And the C++ module remains accessible via that static module_cpp *pointer.
Call the module.cpp's methods (example) in your objective-c method:
CppModule::Result r = module_cpp->CppMethod();
Appears to work absolutely fine!
If anyone can explain the oddities in 4. I'd be grateful.
The module I needed just does some complex (numeric) calculations, and I did not feel like converting that code to Objective-C.
IOS Netbanking sample for Objective c
- (IBAction)Button:(id)sender {
NSMutableArray *userdata=[[NSMutableArray alloc]initWithObjects:#"Name",#"CreditcardNumber",#"Pinnumber",#"Active", nil]; // arrkey = userdata.
NSMutableArray *Yogesh=[[NSMutableArray alloc]initWithObjects:#"Yogesh",#"908380637367",#"5656",#"yes", nil];
NSMutableArray *sabari=[[NSMutableArray alloc]initWithObjects:#"Sabari",#"7635298721",#"6543",#"no",nil];
NSMutableArray *rajesh=[[NSMutableArray alloc]initWithObjects:#"rajesh",#"8373197272",#"8765",#"yes",nil];
NSMutableArray *Ramya =[[NSMutableArray alloc]initWithObjects:#"Ramya ",#"123456",#"9898",#"No",nil];
NSMutableDictionary * dic= [[NSMutableDictionary alloc]initWithObjects:Yogesh forKeys:userdata];
NSMutableDictionary * dic1=[[NSMutableDictionary alloc]initWithObjects:sabari forKeys:userdata];
NSMutableDictionary * dic2=[[NSMutableDictionary alloc]initWithObjects:rajesh forKeys:userdata];
NSMutableDictionary * dic3=[[NSMutableDictionary alloc]initWithObjects:Ramya forKeys:userdata];
/* NSLog(#"%#", dic);
NSLog(#"%#", dic1);
NSLog(#"%#", dic2);*/
NSMutableArray * arraylist=[[NSMutableArray alloc]initWithObjects:dic,dic1,dic2,dic3, nil];
NSLog(#"Array = %#", arraylist);
NSLog(#"user entered value %d", _ccNumber.text.intValue);
NSLog(#"pin number %d ",_pin.text.intValue);
for(int i = 0; i< [arraylist count]; i++){
NSMutableDictionary *dictionary= arraylist[i];
// NSLog(#"userdata is [%d] %#",i,[dictionary objectForKey:#"Pinnumber"]);
NSInteger a;
NSInteger vx;
NSString *b;
NSString *str;
a = (self.ccNumber.text.integerValue);
vx = (self.pin.text.integerValue);
b = ([dictionary objectForKey:#"CreditcardNumber"]);
str = ([dictionary objectForKey:#"Pinnumber"]);
NSInteger c = [b integerValue];
NSInteger d = [str integerValue];
if(a == c && vx == d){
NSLog(#" user data is [%d] Name: %#",i,[dictionary objectForKey:#"Name"]);
NSLog(#" user data is [%d] Card Number: %#",i,[dictionary objectForKey:#"CreditcardNumber"]);
NSLog(#" user data is [%d] Pin Number :%#",i,[dictionary objectForKey:#"Pinnumber"]);
NSLog(#" user data is [%d] Active: %#",i,[dictionary objectForKey:#"Active"]);
}else{
NSString *DataStatus= #"Invalid Card Number";
self.dataStatusLbl.text = DataStatus;
NSLog(#"%#",DataStatus);
}
}
}
#end

Can't find standard C++ includes when using C++ class in Cocoa project

I have a Cocoa project (a Mac OS X app), all Objective-C. I pulled in one C++ class (which I know works) from another project, and make an Objective-C wrapper for it. The ObjC wrapper class is using a .mm extension. However, the C++ header file contains #includes to standard C++ header files (<vector>, for example), and I get errors on those.
A minimal example would look like the following. CppClass is the C++ class, and CppWrapper is the ObjC class which wraps it.
// CppClass.h
#ifndef _CPP_CLASS_H_
#define _CPP_CLASS_H_
#include <vector>
class CppClass
{
public:
CppClass() {}
~CppClass() {}
private:
std::vector<int> my_ints;
};
#endif /* _CPP_CLASS_H_ */
// CppWrapper.h
#import <Foundation/Foundation.h>
#import "CppClass.h"
#interface CppWrapper : NSObject {
CppClass* myCppClass;
}
#end
// CppWrapper.mm
#import "CppWrapper.h"
#implementation CppWrapper
- (id)init
{
self = [super init];
if (self) {
myCppClass = new CppClass;
}
return self;
}
- (void)dealloc
{
delete myCppClass;
[super dealloc];
}
#end
// The file that uses CppWrapper
// TestAppDelegate.m
#import "TestAppDelegate.h"
#import "CppWrapper.h"
#implementation TestAppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
myWrapper = [[CppWrapper alloc] init];
}
#end
The error I'm getting is the #include of vector in CppClass.h. The error is
lexical or Preprocessor issue: 'vector' file not found
This code works fine in another (all C++) project, so I'm pretty sure it's a build setting, or something I've done wrong in the wrapper class. I'm using Xcode 4. I created a default Cocoa Mac OS app project and all settings are default.
Update: I just realized that if I set TestAppDelegate's File Type to Objective-C++ (or rename it to TestAppDelegate.mm), it works. What I don't understand is, this class is pure Objective-C; why does it have to be compiled as Objective-C++? The whole point of having an Objective-C wrapper on my C++ class is so that I don't have to build the entire project as Objective-C++.
The problem with your CppWrapper class is that it doesn't present a pure Objective-C interface. In your CppWrapper.h file, you're importing the C++ class's header file, which means that any Objective-C class that imports the wrapper class will need to be compiled as Objective-C++, including your TestAppDelegate.
Instead, you'd need to do something like this to completely hide the C++ within the CppWrapper.mm file:
// CppWrapper.h
#import <Foundation/Foundation.h>
#interface CppWrapper : NSObject {
void *myCppClass;
}
- (void)doSomethingWithCppClass;
#end
// CppWrapper.mm
#import "CppWrapper.h"
#import "CppClass.h"
#implementation CppWrapper
- (id)init {
self = [super init];
if (self) {
myCppClass = new CppClass;
}
return self;
}
- (void)dealloc {
delete myCppClass;
[super dealloc];
}
- (void)doSomethingWithCppClass {
static_cast<CppClass *>(myCppClass)->DoSomething();
}
#end
Personally, I would
#include "CppClass.h"
instead of importing it.
That's probably not your problem though.